Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос по потокам. [D7, XP]


Страницы:   1 2

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;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо