Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.52/96: Рейтинг темы: голосов - 96, средняя оценка - 4.52
 Аватар для Lionella
2 / 2 / 0
Регистрация: 01.10.2012
Сообщений: 15

Пример простого многопоточного приложения

07.02.2013, 15:09. Показов 19184. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.

Пытаюсь реализовать пример из книги.

Итак, интерфейсный модуль, созданный мастером поточных объектов. В объявление класса TProThread добавлен член данных NT, аргумент конструктора заменен номером текущего потока Thread,и введена функция синхронизации ThreadProgress.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef ThreadUnit2H
#define ThreadUnit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class TProThread : public TThread
{            
private:
        int NT;
protected:
        void __fastcall Execute();
public:
        __fastcall TProThread(int Thread);
        void __fastcall ThreadProgress();
};
//---------------------------------------------------------------------------
#endif
Переопределение метода Execute в кодовом модуле ThreadUnit2.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "ThreadUnit2.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
 
//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall TProThread::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------
 
__fastcall TProThread::TProThread(int Thread)
        : TThread(false)
{
NT = Thread;
FreeOnTerminate = true;
}
//---------------------------------------------------------------------------
void __fastcall TProThread::Execute()
{
while(!Terminated) Synchronize(ThreadProgress);
}
//---------------------------------------------------------------------------
void __fastcall TProThread::ThreadProgress()
{
Form1->pb[NT]->Position++;
if(Form1->pb[NT]->Position >= Form1->pb[NT]->Max)
   {
   Form1->sg->Cells[5][NT+1] = Form1->pbc[NT]++;
   Form1->pb[NT]->Position = 0;
   }
}
ThreadUnit.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef ThreadUnitH
#define ThreadUnitH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <Grids.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TStringGrid *sg;
        TButton *Button1;
        TProgressBar *pb;
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall sgSelectCell(TObject *Sender, int ACol, int ARow,
          bool &CanSelect);
private:    // User declarations
public:     // User declarations
        __fastcall TForm1(TComponent* Owner);
 
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

ThreadUnit.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <vcl.h>
#pragma hdrstop
#include "ThreadUnit2.h"
#include "ThreadUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
 
String tps[7] = {"Idle","Lowest", "Lower", "Normal","Higher","Highest",
                  "TimeCritical"};
bool tsb[1];
String tss[] = {"true", "false"};
int tpi[7];
int pbc[1];
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 
for(int i = 0;i < 8;i++)
   {tsb[i] = false; tss[i] = "false"; tpi[i] = 0; pbc[i] = 1;}
   sg->ColWidths[0] = 52;     sg->Cells[0][0] = "Thread";
   sg->ColWidths[1] = 68;     sg->Cells[1][0] = "ThreadID";
   sg->ColWidths[2] = 80;     sg->Cells[2][0] = "Suspended";
   sg->ColWidths[3] = 80;     sg->Cells[3][0] = "Priority";
   sg->ColWidths[4] = 280;    sg->Cells[4][0] = "Progress";
   sg->ColWidths[5]= 40;      sg->Cells[5][0] = "Pass";
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 
if(t < 8)
  {
ProThread[t] = new TProThread(1);
  sg->Cells[0][t+1] = IntToStr(t+1);
  sg->Cells[1][t+1] = IntToHex((int)ProThread[t]->ThreadID,8);
  sg->Cells[2][t+1] = tss[t];
  sg->Cells[3][t+1] = tps[tpi[t]];
  ProThread[t]->Priority = (TThreadPriority)tpi[t];
  pb[t] = new TProgressBar(sg);   pb[t]->Parent(sg);
  pb[t]->Left = 288;              pb[t]->Top = 27+23*t;
  pb[t]->Width = 272;             pb[t]->Height = 16;
  pb[t]->Max = 10000;
  sg->Cells[5][t+1] = pbc[t];     t++;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sgSelectCell(TObject *Sender, int ACol, int ARow,
      bool &CanSelect)
{
 
int r = ARow - 1;
if(t <= r) return;
if(ACol == 2)
   {
   if(tsb[r])
   {tsb[r] = false; tss[r] = "false";}
   else
   {tsb[r] = true; tss[r] = "true";}
   ProThread[r]->Suspended = tsb[r];
   sg->Cells[2][ARow] = tss[r];
   }
if(ACol == 3)
   {
   tpi[r]++;
   if(tpi[r] > 6) tpi[r] = 0;
   ProThread[r]->Priority = (TThreadPriority)tpi[r];
   sg->Cells[3][ARow] = tps[tpi[r]];
   }
}

Ошибки:
[C++Error] ThreadUnit.cpp 2451 Undefinite symbol `t`
[C++Error] ThreadUnit.cpp 2451 Undefinite symbol `ProThread`
[C++Error] ThreadUnit.cpp 2451 Undefinite symbol `t`
[C++Error] ThreadUnit.cpp 2451 Undefinite symbol `ProThread

Эту переменную t куда только не ставила. Если ее объявить глобальной, то ошибок вылезает полтора десятка...
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
07.02.2013, 15:09
Ответы с готовыми решениями:

Архитектура многопоточного приложения
Добрый вечер! Подскажите правильно ли я использую критическую секцию: Вне всех форм и классов объявляю TCriticalSection *p_cs = new...

Реализовать выход из многопоточного приложения при нажатии сочетания клавиш "Ctrl+С"
Добрый день! Подскажите пжл, как реализоввать выход с многопоточного(консольного) приложения по обработке нажатия клавишь ctrl+c(при этом...

Помогите с компиляцией *.exe файла простого приложения
Всех приветствую и прошу помочь разобраться с проблемой. Я недавно начал изучать язык, но кое-что уже получилось. Я создал простейшее...

10
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
07.02.2013, 17:17
Lionella, зачем лезть в потоки, если ты основу основ не понимаешь, не понимаешь, что такое области видимости, как объявляются переменные? Также, наверняка не понимаешь, что такое класс.
Не понимаешь, что TForm - это класс. void __fastcall TForm1::Button1Click(TObject *Sender) - это функция член класса. Следовательно, если в этой функции инициализируется ProThread[t] = new TProThread(1);,а его определения в cpp файле нет, значит скорее всего в твоей книге учебнике он объявлен тоже членом класса.

файл h
C++
1
2
3
4
5
6
7
8
class TForm {
private:
    // переменные являются закрытыми членами класса
    int t;
    TProThread *ProThread;
public:
    void __fastcall Button1Click(TObject *Sender);
}
файл cpp
C++
1
2
3
4
5
void __fastcall TForm::Button1Click(TObject *Sender) {
        if (t<8) {
        ProThread = new TProThread(1);
    }
}
Добавлено через 2 минуты
Вариант 2

файл h
C++
1
2
3
4
5
class TForm {
private:    
public:
    void __fastcall Button1Click(TObject *Sender);
}
файл cpp
C++
1
2
3
4
5
6
7
8
9
// переменные определены в cpp файле и являются глобальными по отношению ко всему коду,
// который расположен ниже в cpp файле
    int t = 0;
    TProThread *ProThread = 0;
void __fastcall TForm::Button1Click(TObject *Sender) {
    if (t<8) {
        ProThread = new TProThread(1);
    }
}
1
 Аватар для Lionella
2 / 2 / 0
Регистрация: 01.10.2012
Сообщений: 15
07.02.2013, 17:46  [ТС]
Цитата Сообщение от Maluda Посмотреть сообщение
Lionella, зачем лезть в потоки, если ты основу основ не понимаешь, не понимаешь, что такое области видимости, как объявляются переменные? Также, наверняка не понимаешь, что такое класс.
Не понимаешь, что TForm - это класс. void __fastcall TForm1::Button1Click(TObject *Sender) - это функция член класса. Следовательно, если в этой функции инициализируется ProThread[t] = new TProThread(1);,а его определения в cpp файле нет, значит скорее всего в твоей книге учебнике он объявлен тоже членом класса.
Что Вы, я не лезу в потоки. Просто пытаюсь ориентироваться, т.к. вдруг захотелось узнать побольше о программировании и С++ в частности, для начала. Использую то, что есть, в данном случае книгу Шамиса. Бобровского уже поизучала. Что такое класс - я в курсе, НО.. опыта маловато. А желание огромное, и, думаю, мне не стоит этим пренебрегать.
Back to topic, все равно ошибки.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
07.02.2013, 18:08
Лучший ответ Сообщение было отмечено как решение

Решение

Lionella, заархивируй свой проект и выложи. Я отредактирую и скажу, в чём конкретно ошибка

Добавлено через 19 минут
Вот набросал тебе очень простой пример, думаю, что его легче будет понять

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
 
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
 
//---------------------------------------------------------------------------
class TMyThread : public TThread {
public:
 
    TMyThread(const bool CreateSuspended):TThread(CreateSuspended) {};
 
    void __fastcall Execute(void) {
        while (!this->Terminated) {
            Sleep(100);
            this->Synchronize(&UpdateCaption);
        }
    }
 
    void __fastcall UpdateCaption() {
        Form1->Caption = Now().DateTimeString();
    }
};
 
TMyThread *FMyThread = 0;
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
}
 
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnStartClick(TObject *Sender) {
    if (FMyThread) {
        ShowMessage("Thread is already launched");
    }
    else {
        FMyThread = new TMyThread(false);
        FMyThread->FreeOnTerminate = false;
    }
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::BtnStopClick(TObject *Sender) {
    if (FMyThread) {
        FMyThread->Terminate();
        delete FMyThread;
        FMyThread = 0;
    }
}
//---------------------------------------------------------------------------
5
 Аватар для Lionella
2 / 2 / 0
Регистрация: 01.10.2012
Сообщений: 15
07.02.2013, 18:09  [ТС]
Цитата Сообщение от Maluda Посмотреть сообщение
Lionella, заархивируй свой проект и выложи. Я отредактирую и скажу, в чём конкретно ошибка
Ok, спасибо, я буду через полтора часа и выложу.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
07.02.2013, 18:09
На форме две кнопки: одна запускает поток, вторая останавливает.
В потоке в заголовок формы выводится текущее время.
0
 Аватар для Lionella
2 / 2 / 0
Регистрация: 01.10.2012
Сообщений: 15
07.02.2013, 22:15  [ТС]
Проект
Вложения
Тип файла: rar ThreadAr.rar (8.6 Кб, 150 просмотров)
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
08.02.2013, 14:33
Понял, какая задача стояла: то есть по кнопке запустить 7 потоков с различным приоритетом.
По мере выполнения каждый поток должен обновлять соответствующий прогресс. Также необходимо остановить-возобновить работу потока и поменять приоритет.
Твой пример полностью переработал. Обрати внимание на структуру кода, на именование переменных,
на организацию комментариев и т.д.
Что непонятно будет, спрашивай.

ThreadUnit.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "ThreadUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
 
    // маркировка фиксированных ячеек таблицы
    GridThreadData->ColWidths[gctThreadNo] = 52;
    GridThreadData->Cells[gctThreadNo][0] = "Thread";
 
    GridThreadData->ColWidths[gctThreadId] = 68;
    GridThreadData->Cells[gctThreadId][0] = "ThreadID";
 
    GridThreadData->ColWidths[gctSuspend] = 80;
    GridThreadData->Cells[gctSuspend][0] = "Suspended";
 
    GridThreadData->ColWidths[gctPriority] = 80;
    GridThreadData->Cells[gctPriority][0] = "Priority";
 
    GridThreadData->ColWidths[gctProgress] = 80;
    GridThreadData->Cells[gctProgress][0] = "Progress";
 
    GridThreadData->ColWidths[gctPass] = 80;
    GridThreadData->Cells[gctPass][0] = "Pass";
 
    // создадим всплывающее меню, из которого можно будет приостановить поток
    // и поменять приоритет потока
    // ВЛАДЕЛЬЦЕМ УКАЗЫВАЕМ ФОРМУ, 
        // ПОЭТОМУ ПРИ ЗАВЕРШЕНИИ ПРОГРАММЫ ОНА САМА УДАЛИТ ЭТОТ КОМПОНЕНТ
    PopupMenu1 = new TPopupMenu(this);
 
    MenuSuspended = NewItem("Suspended", 0, false, true, &MenuSuspendedClick, 0, "MenuSuspended");
    PopupMenu1->Items->Insert(0, MenuSuspended);
 
    MenuChangepriority = NewItem("Change priority", 0, false, true, 0, 0, "MenuChangepriority");
    PopupMenu1->Items->Insert(0, MenuChangepriority);
 
    for (int i = 0; i < MAX_THREAD_COUNT; i++) {
        ProThread[i] = 0;
 
        TMenuItem *AMenuItem = NewItem(sThreadPriority[i], 0, false, true, &MenuPriorityItemClick,
            0, "Menu" + sThreadPriority[i]);
        AMenuItem->Tag = i;
        MenuChangepriority->Insert(i, AMenuItem);
    }
}
 
//---------------------------------------------------------------------------
void __fastcall TForm1::MenuSuspendedClick(TObject *Sender) {
 
    const int &iThreadId = MenuSuspended->Tag;
 
    if (ProThread[iThreadId]) {
        // если был остановлен - запускаем, а если запущен, приостанавливаем
        ProThread[iThreadId]->Suspended = !ProThread[iThreadId]->Suspended;
 
        GridThreadData->Cells[gctSuspend][iThreadId + 1] = BoolToStr
        (ProThread[iThreadId]->Suspended, true);
    }
    else {
        ShowMessage("Поток ещё не запущен");
    }
}
 
//---------------------------------------------------------------------------
void __fastcall TForm1::MenuPriorityItemClick(TObject *Sender) {
 
    const int &iThreadId = MenuChangepriority->Tag;
 
    if (ProThread[iThreadId]) {
        TMenuItem * AMenuItem = dynamic_cast<TMenuItem*>(Sender);
        if (AMenuItem) {
            // меняем приоритет согласно выбранному элементу в меню
            ProThread[iThreadId]->Priority = TThreadPriority(AMenuItem->Tag);
 
            GridThreadData->Cells[gctPriority][iThreadId + 1] = sThreadPriority[AMenuItem->Tag];
        }
    }
    else {
        ShowMessage("Поток ещё не запущен");
    }
}
 
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnStartClick(TObject *Sender) {
    // флаг, который будет отвечать за то, что действие выполнено единоразово
    static bool bOnce = false;
    if (bOnce) {
        ShowMessage("Программа разрабатывалась для демо режима!"
 
            "\nРазрешается запустить потоки один раз!");
 
        return;
    }
 
    bOnce = true;
 
    // создадим и запустим потоки
    for (int i = 0; i < MAX_THREAD_COUNT; i++) {
        ProThread[i] = new TProThread(i);
        ProThread[i]->Priority = TThreadPriority(i);
 
        // создадим прогресс бар, который будет соответствовать потоку
        m_ProgressBarArray[i] = new TProgressBar(this);
        m_ProgressBarArray[i]->Parent = PanelContainer;
        m_ProgressBarArray[i]->Align = alTop;
        m_ProgressBarArray[i]->Max = 1000;  // величина побольше для наглядности
 
        // сделаем, чтобы прогрессы расположились правильно один над другим
        m_ProgressBarArray[i]->Top = i * m_ProgressBarArray[i]->Height + 3;
 
        // заполним ячейки таблицы данными о процессе
        GridThreadData->Cells[gctThreadNo][i + 1] = IntToStr(i + 1);
        GridThreadData->Cells[gctThreadId][i + 1] = IntToHex((int)ProThread[i]->ThreadID, 8);
        GridThreadData->Cells[gctSuspend][i + 1] = BoolToStr(ProThread[i]->Suspended, true);
        GridThreadData->Cells[gctPriority][i + 1] = sThreadPriority[ProThread[i]->Priority];
        GridThreadData->Cells[gctPass][i + 1] = "Started...";
    }
}
 
//---------------------------------------------------------------------------
 
void __fastcall TForm1::GridThreadDataMouseUp(TObject *Sender, TMouseButton Button,
    TShiftState Shift, int X, int Y) {
 
    if (Button == mbRight) {
 
        // получаем номер колонки и ряда ячейки
        const TGridCoord AGridCoord = GridThreadData->MouseCoord(X, Y);
 
        // щелчок по фиксированным ячейкам
        if (AGridCoord.X == 0 || AGridCoord.Y == 0) {
            return;
        }
 
        TGridRect AGridRect;
        AGridRect.TopLeft = AGridCoord;
        AGridRect.BottomRight = AGridCoord;
 
        // выделяем эту ячейку, так как по щелчку правой кнопки по умолчанию не выделяется
        GridThreadData->Selection = AGridRect;
 
        const TPoint APopupPoint = GridThreadData->ClientToScreen(TPoint(X, Y));
 
        // если щелчок в колонке, где можно приостановить поток, тогда делаем видимым этот пункт меню
        MenuSuspended->Visible = AGridRect.Left == gctSuspend;
        if (MenuSuspended->Visible) {
            const int &iThreadId = AGridRect.Top - 1;
 
            MenuSuspended->Tag = iThreadId;
            if (ProThread[iThreadId]) {
                MenuSuspended->Checked = ProThread[iThreadId]->Suspended;
            }
        }
 
        // если щелчок в колонке с выбором приоритета, тогда делаем видимым этот пункт меню
        MenuChangepriority->Visible = AGridRect.Left == gctPriority;
        if (MenuChangepriority->Visible) {
            const int &iThreadId = AGridRect.Top - 1;
 
            MenuChangepriority->Tag = iThreadId;
            if (ProThread[iThreadId]) {
                for (int i = 0; i < MenuChangepriority->Count; i++) {
                    MenuChangepriority->Items[i]->Checked =
                        MenuChangepriority->Items[i]->Tag == ProThread[iThreadId]->Priority;
                }
            }
        }
 
        // вызываем меню в координатах мыши в таблице
        PopupMenu1->Popup(APopupPoint.x, APopupPoint.y);
    }
}
 
//---------------------------------------------------------------------------
ThreadUnit.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//---------------------------------------------------------------------------
 
#ifndef ThreadUnitH
#define ThreadUnitH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <Grids.hpp>
#include <ExtCtrls.hpp>
#include <Menus.hpp>
 
#include "ThreadUnit2.h"
 
//---------------------------------------------------------------------------
class TForm1 : public TForm {
__published: // IDE-managed Components
    TStringGrid *GridThreadData;
    TButton *BtnStart;
    TPanel *PanelContainer;
 
    void __fastcall BtnStartClick(TObject *Sender);
    void __fastcall GridThreadDataMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift,
        int X, int Y);
 
private:
    // массив-контейнер потоков
    TProThread *ProThread[MAX_THREAD_COUNT]; // User declarations
 
    // всплывающее меню, будет создано динамически в конструкторе
    TPopupMenu *PopupMenu1;
 
    TMenuItem *MenuSuspended;
    TMenuItem *MenuChangepriority;
 
    void __fastcall MenuSuspendedClick(TObject *Sender);
    void __fastcall MenuPriorityItemClick(TObject *Sender);
 
public: // User declarations
    __fastcall TForm1(TComponent* Owner);
 
    // массив-контейнер прогрессбаров, определен для общего доступа,
    // так как должен быть виден из другого класса ( TProThread )
    TProgressBar *m_ProgressBarArray[MAX_THREAD_COUNT];
};
 
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
ThreadUnit2.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "ThreadUnit.h"
 
#include "ThreadUnit2.h"
 
#pragma package(smart_init)
//---------------------------------------------------------------------------
 
//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall TProThread::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------
 
__fastcall TProThread::TProThread(const int iThread) : TThread(false), m_i_CurrentThread(iThread) {
    FreeOnTerminate = true;
}
 
//---------------------------------------------------------------------------
void __fastcall TProThread::Execute() {
    while (!Terminated) {
        Synchronize(ThreadProgress);
        Sleep(16);
    }
}
 
//---------------------------------------------------------------------------
void __fastcall TProThread::ThreadProgress() {
    Form1->m_ProgressBarArray[m_i_CurrentThread]->Position++;
 
    const int iPercent = Form1->m_ProgressBarArray[m_i_CurrentThread]->Position * 100 /
        Form1->m_ProgressBarArray[m_i_CurrentThread]->Max;
 
    Form1->GridThreadData->Cells[gctProgress][m_i_CurrentThread + 1] = AnsiString(iPercent) + " %";
 
    if (Form1->m_ProgressBarArray[m_i_CurrentThread]->Position >= Form1->m_ProgressBarArray
        [m_i_CurrentThread]->Max) {
        Form1->GridThreadData->Cells[gctPass][m_i_CurrentThread + 1] = "Finished!";
        Form1->m_ProgressBarArray[m_i_CurrentThread]->Position = Form1->m_ProgressBarArray
        [m_i_CurrentThread]->Max;
        this->Terminate();
    }
}
ThreadUnit2.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//---------------------------------------------------------------------------
 
#ifndef ThreadUnit2H
#define ThreadUnit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
 
// количество запускаемых потоков
#define MAX_THREAD_COUNT 7
 
// для удобства, чтобы не было путаницы промаркируем именами колонки в таблице
typedef enum {gctThreadNo, gctThreadId, gctSuspend, gctPriority, gctProgress, gctPass} TGridColumnType;
 
static String sThreadPriority[MAX_THREAD_COUNT] = {
    "Idle", "Lowest", "Lower", "Normal", "Higher", "Highest", "TimeCritical"
};
 
//---------------------------------------------------------------------------
class TProThread : public TThread
{            
private:
        // номер текущего потока
        const int m_i_CurrentThread;
        void __fastcall ThreadProgress();
protected:
        void __fastcall Execute();
public:
        __fastcall TProThread(const int iThread);
 
 
};
//---------------------------------------------------------------------------
#endif
1
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
08.02.2013, 14:37
Лучший ответ Сообщение было отмечено как решение

Решение

П.С. Делал всё в C++ Builder 2010. Исходник твоего проекта был сделан, наверное, в C++ Builder 6, его к сожалению установленного нет. Но думаю здесь всё предельно элементарно, поэтому разберёшься.

Брошу на всякий свой проект.

Должно на выходе получиться что-то вроде такого
Миниатюры
Пример простого многопоточного приложения   Пример простого многопоточного приложения  
Вложения
Тип файла: zip ThreadProj.zip (6.12 Мб, 293 просмотров)
4
 Аватар для Lionella
2 / 2 / 0
Регистрация: 01.10.2012
Сообщений: 15
26.02.2013, 23:57  [ТС]
Такое появляется после запуска программы:
Миниатюры
Пример простого многопоточного приложения   Пример простого многопоточного приложения  
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
27.02.2013, 19:12
Пишет, что метакласс TPopupMenu не найден. Странно, потому что обращений по метаклассу вроде никаких в коде нет. Возможно особенности каких-то предыдущих версий билдера. может включение какое-то нужно.
Решение такое: бросить вручную на форму TPopupMenu и посмотреть, какие ещё добавятся файлы в заголовочном формы. Или вообще отказаться от динамического создания.
П.С. А вообще рекомендую перейти на более новую версию Билдера.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.02.2013, 19:12
Помогаю со студенческими работами здесь

GUI через c++ builder для простого консольного приложения
Есть вот такая простая консольная программа,помогите запилить GUI через C++ Builder,лучше всего наверное через StrinG Grid,хотя можно и...

Создание простого приложения для Windows 9x/NT, решил как смог. Пожалуйста подскажите что исправить или добавить
задание: окно фон зелёный размер 500х400 курсор IDT_HAND При закрытии окна вывести ФИО Мой вариант: ...

C++ и WinAPI - пример простого приложения
Можете дать пример простого приложения, которое будет выводить текст в окне Windows (не консоль). P.S. Только начал изучать C++, люблю...

Может, кто-нибудь привести пример простого приложения на фреймворке Slim или Laravel? PHP
Я просто сама не могу разобраться и написать своё что-то

Нужны исходники простого простого приложения под Android для примера
можете дать ссылку на приложение под андроид?не Hello Word а какое нибудь другое но тоже простое на подобие этого ?хочу понять как...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru