Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Builder
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/97: Рейтинг темы: голосов - 97, средняя оценка - 4.57
zizitop
1 / 1 / 0
Регистрация: 17.09.2008
Сообщений: 6
1

Потоки(TThread)

24.09.2008, 20:39. Просмотров 17662. Ответов 15
Метки нет (Все метки)

Здраствуйте. У меня возникла следующая проблема, начал изучать потоки,когда создаю три потока, третий должен запуститься после окочания роботы одного из двух (наважно какой). вот тут ы проблема, Билдер выдаёт ошыбку типа неверный дискриптор. Как можно исправить ошыбку?
главный класс
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
TForm1 *Form1;
mynP1 *thr_1;//поток 1
mynP2 *thr_2;//поток 2
myP3 *thr_3;//поток 3
void __fastcall TForm1::btnStartThreadsClick(TObject *Sender)
{
thr_1=new mynP1(true); 
thr_2=new mynP2(true);
thr_3=new myP3(true);
//thr_1->Priority=tpIdle;
//thr_2->Priority=tpIdle;
thr_1->FreeOnTerminate=true;
thr_2->FreeOnTerminate=true;
thr_3->FreeOnTerminate=true;
switch(RadioGroup1->ItemIndex)
{
case 0:{thr_1->Priority=tpIdle;thr_2->Priority=tpIdle;}break;
case 1:{thr_1->Priority=tpHigher;thr_2->Priority=tpHigher;}break;
case 2:{thr_1->Priority=tpHighest;thr_2->Priority=tpHighest;}break;
default : {thr_1->Priority=tpNormal;thr_2->Priority=tpNormal;}break;
}
thr_1->Resume();
thr_2->Resume();
thr_3->Resume();
}
поток 3:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
extern mynP2 *thr_2;
void __fastcall myP3::Execute()
{
        //---- Place thread code here ----
thr_2->WaitFor();//ожыдаем его завершения
summ3=0;
for(int i=0;i<=10000;i++)
{
//Application->ProcessMessages();
//Form1->ProgressBar1->Position=i;
summ3+=i-sin(i*M_PI/180);
}
 Form1->Memo1->Lines->Add("P3:"+ FloatToStr(summ3));
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.09.2008, 20:39
Ответы с готовыми решениями:

Потоки, TThread, нет синхронизации
Доброго дня, товарищи программисты. Проблемка тут у меня с потоком. Я создаю...

TThread, TThread, TThread .......... %)
помогите, если не затруднит как можно динамически создать поток и передать...

TThread и ShowMessage
Пискал ответ на проблему в гугле - вижу, что проблема довольно масштабная, т.к....

Клас TThread
Нужно написать програму для реализации потоков через клас TThread. Когда я...

Не работает Synchronize в TThread
Доброго времени суток! .h class TMyThread : public TThread { private:...

15
Vovan-VE
13160 / 6545 / 1038
Регистрация: 10.01.2008
Сообщений: 15,070
25.09.2008, 18:24 2
Из потоков обращаться напрямую к форме и тем более к ее компонентам - это очень плохая идея. Я в таких случаях посылаю форме свои мессаги с нужными параметрами.
0
zizitop
1 / 1 / 0
Регистрация: 17.09.2008
Сообщений: 6
25.09.2008, 19:55  [ТС] 3
Да, я с вами соласен, можно либо использовать Synhronize() либо посылать сообщения, но согласно задания использоваиня VCL компонент в программе - допускаеться. Мне важно как правильно в моём случае использовать ф-ю WaitFor?
0
Vovan-VE
13160 / 6545 / 1038
Регистрация: 10.01.2008
Сообщений: 15,070
26.09.2008, 07:23 4
WaitFor() ждет пока поток не совсем не завершится. Если она никак не может дождаться, то это значит, что второй поток не завершается. Можно код второго потока?
0
zizitop
1 / 1 / 0
Регистрация: 17.09.2008
Сообщений: 6
26.09.2008, 15:02  [ТС] 5
код второго потока:
C++
1
2
3
4
5
6
7
8
9
10
11
void __fastcall mynP2::Execute()
{
summ=0;
for(int i=0;i<=10000;i++)
{
//Application->ProcessMessages();
//Form1->ProgressBar1->Position=i;
summ+=sin(i*M_PI/180);
}
 Form2->Memo2->Lines->Add("P2:"+ FloatToStr(summ));
}
Такую же ошибку можно вызвать, если после завершения роботы потока, вызвать метод Suspend() етого потока. Возможно я не там прописал WaitFor()? или метод Resume третьего потока надо запускать в другом месте?
0
Vovan-VE
13160 / 6545 / 1038
Регистрация: 10.01.2008
Сообщений: 15,070
26.09.2008, 16:14 6
А может третий поток надо запускать раньше, чем второй? Может второй уже успевает сделать Free()?
0
zizitop
1 / 1 / 0
Регистрация: 17.09.2008
Сообщений: 6
26.09.2008, 16:50  [ТС] 7
ксожалению третий должен начать роботать только после завершения второго (такое задание). И как раз для етого есть ф-я WaitFor(). Она, как мне кажеться ждёт когда закончит роботу один поток и запускает следующий.(я делал ету програму по примеру из книги Архангельского)
0
Vovan-VE
13160 / 6545 / 1038
Регистрация: 10.01.2008
Сообщений: 15,070
26.09.2008, 21:28 8
Нет, я имел ввиду вот это:
C++
1
2
3
4
5
}
thr_1->Resume();
thr_2->Resume();
thr_3->Resume();
}
Запустить сначала третий, а потом второй.
C++
1
2
3
4
5
}
thr_1->Resume();
thr_[b]3[/b]->Resume();
thr_[b]2[/b]->Resume();
}
Все равно третий не начнет работать раньше второго.
0
zizitop
1 / 1 / 0
Регистрация: 17.09.2008
Сообщений: 6
27.09.2008, 19:47  [ТС] 9
я тоже пробовал тоже так делать- все одно таже ошибка. Сейчас переделал слегка прогу тепер после окончания одного потока сразу запускаю следюший(в методе Execute). Но все одно непонимаю как запустить поток методом WaitFor? Vovan-VE может вы использовали етот метод WaitFor или маете пример с ним? Просто из-за принцыпа интересно как же с ним роботать
0
Vovan-VE
13160 / 6545 / 1038
Регистрация: 10.01.2008
Сообщений: 15,070
27.09.2008, 22:07 10
Вообще с потоками почти всегда такая муть. Как ни крути-мути, все равно бывают случаи с ошибками.
0
Evg
Эксперт CАвтор FAQ
19311 / 7166 / 533
Регистрация: 30.03.2009
Сообщений: 20,049
Записей в блоге: 30
25.11.2009, 11:07 11
Цитата Сообщение от Vovan-VE Посмотреть сообщение
Из потоков обращаться напрямую к форме и тем более к ее компонентам - это очень плохая идея. Я в таких случаях посылаю форме свои мессаги с нужными параметрами.
Почему? Вот тут написано следующее:

Другая отличительная черта класса TThread — это гарантия безопасной работы с библиотекой визуальных компонентов VCL. Без использования класса TThread во время вызовов VCL могут возникнуть ситуации, требующие специальной синхронизации (см. разд. "Проблемы при синхронизации потоков" далее в этой главе).
Насколько я понимаю, класс разрабатывался именно с тем свойством, чтобы можно было из потоков напрямую обращаться к компонентам формы. Или за этой фразой кроется какой-то другой смысл?

Добавлено через 47 минут
Хотя далее написано про Synchronize. Видимо это оно и есть
0
Фенрир
42 / 38 / 12
Регистрация: 05.01.2009
Сообщений: 394
25.11.2009, 16:15 12
если нужно понять как устроены классы VCL то удобно смотреть исходники на делфи!
вот например процедура Synchronize
Delphi
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
       TThreadMethod = procedure of object;
 
 PSynchronizeRecord = ^TSynchronizeRecord;
  TSynchronizeRecord = record
    FThread: TObject;
    FMethod: TThreadMethod;
    FSynchronizeException: TObject;
  end;
 
 
 
class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord);
var
  SyncProc: TSyncProc;
begin
  if GetCurrentThreadID = MainThreadID then
    ASyncRec.FMethod
  else
  begin
{$IFDEF MSWINDOWS}
    SyncProc.Signal := CreateEvent(nil, True, False, nil);
    try
{$ENDIF}
{$IFDEF LINUX}
      FillChar(SyncProc, SizeOf(SyncProc), 0);  // This also initializes the cond_var
{$ENDIF}
      EnterCriticalSection(ThreadLock);
      try
        if SyncList = nil then
          SyncList := TList.Create;
        SyncProc.SyncRec := ASyncRec;
        SyncList.Add(@SyncProc);
        SignalSyncEvent;
        if Assigned(WakeMainThread) then
          WakeMainThread(SyncProc.SyncRec.FThread);
{$IFDEF MSWINDOWS}
        LeaveCriticalSection(ThreadLock);
        try
          WaitForSingleObject(SyncProc.Signal, INFINITE);
        finally
          EnterCriticalSection(ThreadLock);
        end;
{$ENDIF}
{$IFDEF LINUX}
        pthread_cond_wait(SyncProc.Signal, ThreadLock);
{$ENDIF}
      finally
        LeaveCriticalSection(ThreadLock);
      end;
{$IFDEF MSWINDOWS}
    finally
      CloseHandle(SyncProc.Signal);
    end;
{$ENDIF}
    if Assigned(ASyncRec.FSynchronizeException) then raise ASyncRec.FSynchronizeException;
  end;
end;
0
Evg
Эксперт CАвтор FAQ
19311 / 7166 / 533
Регистрация: 30.03.2009
Сообщений: 20,049
Записей в блоге: 30
25.11.2009, 16:52 13
Про Synchronize я, если честно, толком не понял, как сие использовать

Добавлено через 55 секунд
Фенрир, а у тебя есть короткий пример, как задача в потоке на форму что-то отображает. А ещё я не понял, какие есть средства синхронизации. Для потоков в линухе используются mutex'ы, а что в винде?
0
Evg
Эксперт CАвтор FAQ
19311 / 7166 / 533
Регистрация: 30.03.2009
Сообщений: 20,049
Записей в блоге: 30
25.11.2009, 20:53 14
Ещё вопрос. Создаю программу примерно по следующей схеме. Как в примерах создаю производный класс, устанавливаю в конструкторе FreeOnTerminate в true, а в конце процедуры Execute ещё и на всякий случай "delete this" написал.

В программе работает таймер с интервалом в 1 секунду. На каждую активацию таймера создаю новый процесс, который исполняется, что-то там себе считает и выходит. На всё это уходит заведомо меньше секунды. Получается так, что каждую секунду я создаю новый поток. При запуске из IDE в информационной строке мне об этом постоянно сообщается, т.е. на каждый созданный поток печатается строка, что создался новый поток (Thread Start: Thread ID: ....). И вроде бы по такой логике поток при завершении работы метода Execute должен удаляться. Однако если погонять программу несколько секунд, после чего закрыть программу, то в информационном окне IDE вылезает целая пачка сообщений (Thread Exit: Thread ID: ....). Что это означает? Что потоки реально не были удалены или это какие-то особенности запуска из-под IDE? Запускаю в Release-версии, т.е. вроде бы как без отладчика должно?
0
Evg
Эксперт CАвтор FAQ
19311 / 7166 / 533
Регистрация: 30.03.2009
Сообщений: 20,049
Записей в блоге: 30
06.12.2009, 17:58 15
Цитата Сообщение от Evg Посмотреть сообщение
Ещё вопрос. Создаю программу примерно по следующей схеме. Как в примерах создаю производный класс, устанавливаю в конструкторе FreeOnTerminate в true, а в конце процедуры Execute ещё и на всякий случай "delete this" написал.

В программе работает таймер с интервалом в 1 секунду. На каждую активацию таймера создаю новый процесс, который исполняется, что-то там себе считает и выходит. На всё это уходит заведомо меньше секунды. Получается так, что каждую секунду я создаю новый поток. При запуске из IDE в информационной строке мне об этом постоянно сообщается, т.е. на каждый созданный поток печатается строка, что создался новый поток (Thread Start: Thread ID: ....). И вроде бы по такой логике поток при завершении работы метода Execute должен удаляться. Однако если погонять программу несколько секунд, после чего закрыть программу, то в информационном окне IDE вылезает целая пачка сообщений (Thread Exit: Thread ID: ....). Что это означает? Что потоки реально не были удалены или это какие-то особенности запуска из-под IDE? Запускаю в Release-версии, т.е. вроде бы как без отладчика должно?
Причина это кроется в том, что я реализовал так и этот самый delete и испортил картину. Правильно делать так
0
DISconnect
4 / 4 / 1
Регистрация: 28.11.2009
Сообщений: 6
06.12.2009, 18:28 16
А без WaitFor совсем не обойтись?
Можно навоять обработчик собыйти Thread->OnTerminate.
Присвоить его двум первым потокам. В обработчике создать проверку на то, что 3-й поток не запущен и в этом случае запустить его. Вот и всё шаманство.
0
06.12.2009, 18:28
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.12.2009, 18:28

Tthread доступ к переменным
Здравствуйте, подскажите, пожалуйста, как использовать объявленную в потоке...

TThread и копирование файлов
Добрый день спецы. Пишу достаточно сложную программу, точнее оптимизирую то,...

TThread,Terminate() и Terminated
Как можно проверить остановлен ли поток и как остановить поток в версиях...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru