![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос по потокам. [D7, XP]
dabreezy © (2006-02-07 18:57:00)Добрый вечер.
У меня такой вопрос по потокам (целый день башку ломаю)
есть процедура запуска потока (в ней цикл с сложными вычислениями):
procedure TMyThread1.Execute;
begin
...
repeat
until (terminated) or (i1=i-1);
...
synchronize (Thread_done);
end;
Далее функция Thread_done (thread_running - кол-во потоков):
procedure TMyThread1.Thread_done;
begin
form1.thread_running:=form1.thread_running-1;
end;
Так вот такая штука получается, когда все потоки завершены, то получается что иногда работает нормально(thread_runnig=0), а иногда thread_running=1 или 2. Причем чем больше потоков, тем чаще такое бывает! При 3х-6 потоков такое практически не бывает.
Объясните пожалуйста в чем дело.
begin...end (2006-02-08 13:20:00) [1]> Defunct © (08.02.06 02:36) [21]
> Поэтому если хотите вести конструктивный диалог со мной,
> то для начала высказывайте свою точку зрения, а потом задавайте
> вопрос.
Я сам решаю, когда мне высказывать свою точку зрения, и высказывать ли её вообще. Если же в обсуждении какое-то сообщение вызывает у меня вопрос и я хочу его задать, я его задаю (что я и сделал в этой ветке). Отвечать или нет -- разумеется, личное дело того, кому этот вопрос адресуется. И если кто-то за обычным уточняющим вопросом видит желание "подколоть", то это его проблемы.
> В дальнейшем я буду игнорировать все ваши двусмысленные
> ("короткие") сообщения в мой адрес, как потенциально опасные
> для меня.
No comments.
dabreezy (2006-02-08 10:44:00) [2]
> Leonid Troyanovsky © (08.02.06 09:18) [25]
>
> > dabreezy (08.02.06 08:51) [23]
>
> > Может это как раз и происходило из-за того что :"Create
>
> > и назначением OnTerminate может случиться немало колов
>
> > времени."?
>
>
> Если вчерашнее тестирование проводилось с приведенным кодом
> и
> OnTerminate, а 1 из файлов не создавался (т.е., поток не
> стартовал),
> то, видимо, причина не в этом.
>
> Вообще-то, кроме ранее рассмотренного, на наблюдаемую картину
>
> могут повлиять :
> - молчаливые исключения типа EAbort в конструкторе потока;
>
> - любые исключения в Execute: поток завершится, а до Synchronize(.
> .)
> дело не дошло (однако, OnTerminate будет выполнен).
>
> --
> Regards, LVT.
Спасибо за ответы. Сейчас тестирую, даже с 50 потоками работает как часы :)
Leonid Troyanovsky (2006-02-08 09:18:00) [3]
> dabreezy (08.02.06 08:51) [23]
> Может это как раз и происходило из-за того что :"Create
> и назначением OnTerminate может случиться немало колов
> времени."?
Если вчерашнее тестирование проводилось с приведенным кодом и
OnTerminate, а 1 из файлов не создавался (т.е., поток не стартовал),
то, видимо, причина не в этом.
Вообще-то, кроме ранее рассмотренного, на наблюдаемую картину
могут повлиять :
- молчаливые исключения типа EAbort в конструкторе потока;
- любые исключения в Execute: поток завершится, а до Synchronize(..)
дело не дошло (однако, OnTerminate будет выполнен).
--
Regards, LVT.
evvcom (2006-02-08 09:10:00) [4]
> Может это как раз и происходило из-за того что :"Create
> и назначением OnTerminate может случиться немало колов
> времени."?
Легко. Добавлю к тому, что Inc(thread_running) лучше сделать между Create и Resume.
dabreezy (2006-02-08 08:51:00) [5]
> Leonid Troyanovsky © (08.02.06 08:41) [22]
>
> > dabreezy (07.02.06 20:10) [15]
>
> > Пробовал делать так:
>
>
> Так - уже лучше. Хотя, конечно, еще лучше было б
> Thread_array[i]:=TMyThread1.Create(True), с завершающим
> Resume,
> бо между Create и назначением OnTerminate может случиться
> немало
> колов времени.
>
> Ну, и, наконец, а как определяется то, что все потоки завершились
>
> (в то время, как thread_running > 0) ?
Да, так работает вроде лучше, сейчас тестирую. thread_running проверяется в процедуре обработки onterminate.
Кстати вчера долго тестировал, оказалось, что программа глючила(т.е. оставался один не завершенный поток) из-за того что 1 из 25 потоков, а то и 2 не запускались вообще(проверил это просто, сделал что каждый поток создавал уникальный файл) и вот когда программа глючила как раз файлов было не 25 а 24. Когда работала нормально то файлов было 25. Может это как раз и происходило из-за того что :"Create и назначением OnTerminate может случиться немало колов времени."?
Leonid Troyanovsky (2006-02-08 08:41:00) [6]
> dabreezy (07.02.06 20:10) [15]
> Пробовал делать так:
Так - уже лучше. Хотя, конечно, еще лучше было б
Thread_array[i]:=TMyThread1.Create(True), с завершающим Resume,
бо между Create и назначением OnTerminate может случиться немало
колов времени.
Ну, и, наконец, а как определяется то, что все потоки завершились
(в то время, как thread_running > 0) ?
--
Regards, LVT.
Defunct (2006-02-08 02:36:00) [7]/offtop
2 begin...end
я често сказать, не знаю, как множно с вами общаться. почти во всех ветках с вашим участием наблюдаю с вашей стороны желание поставить меня в неловкое положение или как это называется на базарном языке желание "подколоть". Поэтому если хотите вести конструктивный диалог со мной, то для начала высказывайте свою точку зрения, а потом задавайте вопрос. В данном случае я не буду отвечать на ваш вопрос до тех пор пока вы не расскажете всем чем в контексте вопроса автора применение Synchronize + обращения к глобальным переменным лучше или сравнимо с PostMessage. В дальнейшем я буду игнорировать все ваши двусмысленные ("короткие") сообщения в мой адрес, как потенциально опасные для меня.
Defunct (2006-02-08 01:40:00) [8]> А что плохого в использовании Synchronize?
вести с вами диалог мне не доставляет удовольствия, к тому же у вас есть "знак отличия", который дает мне понять, что темой вы прекрастно владеете.
YuRock (2006-02-07 22:05:00) [9]
> Я просто не понял, чем Synchronize хуже PostMessage в контексте
> проблемы автора.
Так более просто, а значит - надежно. И быстрее. А это лучше в любом контексте.
begin...end (2006-02-07 21:46:00) [10]> YuRock © (07.02.06 21:39) [17]
Я просто не понял, чем Synchronize хуже PostMessage в контексте проблемы автора.
YuRock (2006-02-07 21:39:00) [11]
> А что плохого в использовании Synchronize?
Ну хотя бы добавление необязательных тормозов из-за критических секций и wait'ов, которые использует этот метод.
Если не нужна синхронность (а она тут вряд-ли нужна - я телепат :), то лучший вариант - PostMessage.
begin...end (2006-02-07 20:12:00) [12]> Defunct © (07.02.06 19:42) [8]
> Хотя бы тем что не потребуется использовать Synchronize
А что плохого в использовании Synchronize?
dabreezy (2006-02-07 20:10:00) [13]> Это может сделать любой, у кого есть хендл потока.
> Но, кажется мне, что собака рылась в другом.
> Покажи OnTerminate.
Пробовал делать так:
в объявлении класса формы:
private
procedure Thread_Done(Sender: TObject);
в цикле
thread_kol:=25;
for i:=1 to Thread_kol do
begin
Thread_array[i]:=TMyThread1.Create(false);
Thread_array[i].str:=inttostr(i);
Thread_array[i].OnTerminate:=Thread_done;
inc(Thread_running);
end;
procedure TForm1.Thread_done(Sender: TObject);
begin
Dec(Thread_running);
if thread_running=0 then
begin
...
end;
end;
Leonid Troyanovsky (2006-02-07 19:56:00) [14]
> dabreezy (07.02.06 19:50) [11]
> > И при условии, что потокам не делают TerminateThre
> А кто это может делать? Windows? В программе ничего такого
> не делается.
Это может сделать любой, у кого есть хендл потока.
Но, кажется мне, что собака рылась в другом.
Покажи OnTerminate.
--
Regards, LVT.
Leonid Troyanovsky (2006-02-07 19:52:00) [15]
> dabreezy (07.02.06 19:45) [9]
> Соответственно точно известно что потоков запущено 25.
Точнее было б делать inc(thread_running) в конце цикла.
--
Regards, LVT.
dabreezy (2006-02-07 19:51:00) [16]
> Defunct © (07.02.06 19:42) [8]
> Zeqfreed © (07.02.06 19:22) [5]
> Хотя бы тем что не потребуется использовать Synchronize
>
> dabreezy (07.02.06 19:19) [4]
> > А как это сделать
Спасибо большое. Попробую. Надеюсь получится
dabreezy (2006-02-07 19:50:00) [17]
> Leonid Troyanovsky © (07.02.06 19:48) [10]
>
> > Leonid Troyanovsky © (07.02.06 19:40) [7]
>
> > Нормально должно работать в OnTerminate, при условии,
> конечно,
> > что thread_runnung инкрементируется правильно.
>
>
> И при условии, что потокам не делают TerminateThre
А кто это может делать? Windows? В программе ничего такого не делается.
Leonid Troyanovsky (2006-02-07 19:48:00) [18]
> Leonid Troyanovsky © (07.02.06 19:40) [7]
> Нормально должно работать в OnTerminate, при условии, конечно,
> что thread_runnung инкрементируется правильно.
И при условии, что потокам не делают TerminateThread.
--
Regards, LVT.
dabreezy (2006-02-07 19:45:00) [19]
>
> Нормально должно работать в OnTerminate, при условии, конечно,
>
> что thread_runnung инкрементируется правильно.
Я запускаю потоки вот так:
Thread_array: array [1..50] of TMyThread1;
...
thread_kol:=25;
thread_running:=thread_kol;
for i:=1 to Thread_kol do
begin
Thread_array[i]:=TMyThread1.Create(false);
Thread_array[i].str:=inttostr(i);
end;
Соответственно точно известно что потоков запущено 25. Вот от thread_running и отнимается по единице когда какой-нибуть поток остановлен.
Defunct (2006-02-07 19:42:00) [20]Zeqfreed © (07.02.06 19:22) [5]
Хотя бы тем что не потребуется использовать Synchronize
dabreezy (07.02.06 19:19) [4]
> А как это сделать?
например так:
в модуле описанием потока:
const WM_THREADDONE = WM_USER + 1;
type
TMyThread = class(TThead)
...
protected
FOwnerWnd : HWND;
procedure Execute;
public
constructor Create( AOwnerWND: HWND);
end;
constructor TMyThread.Create;
begin
inherited Create( true );
FOwnerWND := AOwnerWND;
...
resume;
end;
procedure TMyThread.Execute;
begin
...
PostMessage( FOwnerWND, WM_THREADDONE, 0, 0);
end;
в модуле с формой:
TForm1 = class(TForm)
...
procedure ThreadDoneHandler( var Msg: TMessage);message WM_THREADDONE;
procedure StartThread;
end;
procedure TForm1.ThreadDoneHandler;
begin
dec( Thread_running )
end;
procedure StartThread;
begin
try
TMyThread.Create( Handle );
inc( Thread_running );
except
ShowMessage(' could not start new thread' )
end;
end;