Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Завершение потока


Автор: ZBugz 6.1.2010, 14:12
Всем привет. Первый раз пользую потоки  smile 
Все работает, потоки - сила.
Но вот столкнулся с такой проблемой, поток пошел в execute, все пашет, жму кнопку, делаеться Terminate указанного потока. Удаляю данные из ячейки,  и меня в ошибку выкидывает.
А выкидывает потому что поток еще не Terminate, а где то TCopyThread.Progress шатаеться...  smile 
Ну и я тут в ступоре, как сделать так, что бы дождаться его Terminate ? smile 
Так пробывал:
Код

try
   CT[StrToInt(Lv.Items[j].SubItems[9])].Terminate;
 finally

Не помогает :(

Тока с примером, если можно, а то для меня потоки это темный лес  smile Учу пока их...

Автор: RA 6.1.2010, 16:11
Цитата

Как узнать что поток остановлен


Ну если не вешать всяких своих проверок то по пришествию события OnTerminate.  



А так по сути проблемы не мешало бы код увидеть ...

Автор: artsb 6.1.2010, 18:51
ZBugz, вызов метода Terminate не уничтожает поток, а лишь взводит флаг Terminated, который нужно проверять в потоке и если он взведён, завершать его работу.

Ну а проверить завершился ли поток можно функцией GetExitCodeThread. В lpExitCode заносится код завершения потока либо STILL_ACTIVE, если поток ещё работает.

Автор: Демо 7.1.2010, 23:01
ZBugz, 

В реализации Delphi есть метод WaitFor для ожидания завершения поточной функции.
Использовать можно в случае FreeOnTerminate=False;

т.е.

Код

MyThread.WaitFor;
MyThread.Free;


Если нужна периодическая проверка, тогда можно периодически проверять результат функции 
Код

WaitForSingleObject(MyThread.Handle, 0);

Автор: ZBugz 8.1.2010, 13:03
Народ, я ничего не понял вообще  smile 
Код выложить пока не могу, негде написать пример...

Автор: ZBugz 8.1.2010, 13:25
А в проекте так:
Код

procedure TCopyThread.Execute;
begin
//чето делаем
Application.ProcessMessages;
 if Terminated then
    begin
        break;
     end;
end;
constructor TCopyThread.Create(Suspended: boolean; );
begin
  inherited Create (Suspended);
  LineIndex:= ILineIndex;
  TaskIndex:= ITaskIndex;
end;

И вот где брейк, что то надо делать, что бы ждать когда он завершиться....
Код

TCopyThread.CurrentThread.Terminate; и т.д.
 не катит :(

Добавлено через 1 минуту и 12 секунд
Нажимаею кнопку и передаю
Код

CT[idx].Terminate;

Где idx номер потока котрый грохнуть

Автор: artsb 8.1.2010, 14:39
Код

 if Terminated then
    begin
        // убираемся за собой (удаляем динамически созданные объекты и т.п.)
       exit;
     end;

Автор: ZBugz 8.1.2010, 14:58
Цитата(artsb @ 8.1.2010,  14:39)
Код

 if Terminated then
    begin
        // убираемся за собой (удаляем динамически созданные объекты и т.п.)
       exit;
     end;

Так все удаляю, ща вот точнее как у меняя там:

Код

procedure TCopyThread.Execute;
begin
  try
//чето делаем
Application.ProcessMessages;
 if Terminated then
    begin
        break;
     end;
  finally
   // а тут я делаю всем free
  if Stream<>nil then FreeAndNil(Stream);
end;

То что free не срабатывает, это я понял давно, точнее он то срабатывает, а поток в это время гуляет TCopyThread.Progress
Мне бы как то это бы отловить бы, что пока он не завершиться, free не делать...

Автор: artsb 8.1.2010, 17:08
Цитата(ZBugz @  8.1.2010,  14:58 Найти цитируемый пост)
if Stream<>nil then FreeAndNil(Stream);

Вы что, пытаетесь уничтожить поток внутри него же?

ИМХО у вас вообще организация неправильная. Что вы хотите сделать вообще? Какова цель?

Автор: ZBugz 8.1.2010, 19:38
Цитата(artsb @ 8.1.2010,  17:08)
Цитата(ZBugz @  8.1.2010,  14:58 Найти цитируемый пост)
if Stream<>nil then FreeAndNil(Stream);

Вы что, пытаетесь уничтожить поток внутри него же?

ИМХО у вас вообще организация неправильная. Что вы хотите сделать вообще? Какова цель?

Не обращайте внимания, это я для примера так написал.
Я смысл хотел передать, что Terminated в Execute срабатывает, в finally выходит вроде, все делаеться, но на самом деле он не звершен  smile 

И еще, я не знаю, поможет или нет, но когда только создаю поток, он успешно рубиться в  Execute, а все синхронайзы(Progress), т.е. вывода информации, как то сначала запаздуют с отображением, а то ка потом вся инфа идет. И точно так же получаеться что он и выходит их  Execute  smile Т.е. с тормозом.

Мне бы какой нить цикл, который ждал бы завершения именно этого потока, а потом уже вываливался в тот же 
Код

if Stream<>nil then FreeAndNil(Stream);


Добавлено через 1 минуту и 23 секунды
Цитата(artsb @ 8.1.2010,  17:08)
Цитата(ZBugz @  8.1.2010,  14:58 Найти цитируемый пост)
if Stream<>nil then FreeAndNil(Stream);

Вы что, пытаетесь уничтожить поток внутри него же?

ИМХО у вас вообще организация неправильная. Что вы хотите сделать вообще? Какова цель?

Кстати, а почему это не прокатит ? Поток потоком, а stream - стримом. Они же не пересекаються никаким способом.... ?!

Автор: artsb 8.1.2010, 21:01
Цитата(ZBugz @  8.1.2010,  19:38 Найти цитируемый пост)
что Terminated в Execute срабатывает, в finally выходит вроде, все делаеться, но на самом деле он не звершен

Terminated  - это флаг, который взводится при вызове метода потока Terminate. При проверке этого флага внутри Execute, можно убраться за собой и выйти из функции (хотя можно и проигнорировать флаг smile), тем самым завершив работу потока. После этого из основного потока можно уничтожить объект отработавшего потока.

Цитата(ZBugz @  8.1.2010,  19:38 Найти цитируемый пост)
И еще, я не знаю, поможет или нет, но когда только создаю поток, он успешно рубиться в  Execute, а все синхронайзы(Progress), т.е. вывода информации, как то сначала запаздуют с отображением, а то ка потом вся инфа идет. И точно так же получаеться что он и выходит их  Execute

ИМХО это из-за синхронизации.

Цитата(ZBugz @  8.1.2010,  19:38 Найти цитируемый пост)
Кстати, а почему это не прокатит ?

Ох. Сори. Я что-то подумал, что это объект потока.

Добавлено через 1 минуту и 3 секунды
А где вы создаёте Stream?

Автор: ZBugz 8.1.2010, 21:19
Цитата(artsb @ 8.1.2010,  21:01)
Terminated  - это флаг, который взводится при вызове метода потока Terminate. При проверке этого флага внутри Execute, можно убраться за собой и выйти из функции (хотя можно и проигнорировать флаг smile), тем самым завершив работу потока. После этого из основного потока можно уничтожить объект отработавшего потока.

Так вот, я делаю все, а оно делаеться, но с опозданием. Т.е. все работает, в 99%, а в оставшемся случае, тупо не успевает уничтажаться.

Добавлено @ 21:19
Цитата

А где вы создаёте Stream?

Прям в Execute.
Вроде как одно другому не мешает smile 

Автор: artsb 8.1.2010, 22:14
Цитата(ZBugz @  8.1.2010,  21:19 Найти цитируемый пост)
Прям в Execute.

Так и уничтожайте там же. После проверки флага Terminated, уничтожте и выходите из функции. Или Stream в это время ещё нужна?

Добавлено через 4 минуты и 21 секунду
Цитата(ZBugz @  8.1.2010,  21:19 Найти цитируемый пост)
Так вот, я делаю все, а оно делаеться, но с опозданием. Т.е. все работает, в 99%, а в оставшемся случае, тупо не успевает уничтажаться.

задержку при старте можно объяснить синхронизацией ИМХО, а вот по поводу того что у вас в конце там тормозит, я так и не понял толком  smile 

Цитата(ZBugz @  8.1.2010,  21:19 Найти цитируемый пост)
Вроде как одно другому не мешает

Ага.

Автор: ZBugz 9.1.2010, 09:16
Цитата

Так и уничтожайте там же. После проверки флага Terminated, уничтожте и выходите из функции. Или Stream в это время ещё нужна?

Не, не нужна. Я ее там же и уничтажаю. Выше в код е написанно, что грохаю все.
Цитата
задержку при старте можно объяснить синхронизацией ИМХО, а вот по поводу того что у вас в конце там тормозит, я так и не понял толком  smile 

smile Я имел ввиду что free во всю делаеться, а поток почему то в синхронайзе(progress) гуляет.
Код

procedure TCopyThread.Execute;
begin
  try
//чето делаем
Application.ProcessMessages;
синхронайз(progress) <-гуляет тут, но...
 if Terminated then
    begin
        break;
     end;
  finally
   // ... на самом деле уже выполняеться или выполнилось free
  if Stream<>nil then FreeAndNil(Stream);
end;

Автор: artsb 9.1.2010, 10:10
Код

// ... на самом деле уже выполняеться или выполнилось free

эм... не верю smile как такое может быть. ИМХО вы что-то не договариваете   smile

Добавлено через 4 минуты и 57 секунд
Т.е. вы хотите сказать, что это работает:
Код

синхронайз(progress) <-гуляет тут, но...

, а Stream уже уничтожен?

Добавлено через 6 минут и 25 секунд
Кстати, у вас в коде проверка Terminated стоит в самом конце. Там от неё толку нет  smile 

Автор: ZBugz 9.1.2010, 11:29
Цитата

эм... не верю smile как такое может быть. ИМХО вы что-то не договариваете   smile

Дык вот именно так. Сам в шоке  smile 
Цитата

Т.е. вы хотите сказать, что это работает:
Код

синхронайз(progress) <-гуляет тут, но...

, а Stream уже уничтожен?

Ага  smile  Т.е. условие выполняеться->выполнилось, а он гуляет где то. Это дебаггер показывает...
И я вот тут в ступоре, как это отловить...  smile 
Ща одна мысля появилась, потестю пока ее.
Цитата

Кстати, у вас в коде проверка Terminated стоит в самом конце. Там от неё толку нет  smile

Всмысле ?

Автор: artsb 9.1.2010, 11:56
Странно...
А что у вас в функции "progress"?

Цитата(ZBugz @  9.1.2010,  11:29 Найти цитируемый пост)
Всмысле ? 

Это:
Код

 if Terminated then
    begin
        break;
     end;

стоит в самом конце функции. Какой толк от этого? Циклов у вас не наблюдается. Хотя может вы не весь код привели...

Автор: ZBugz 9.1.2010, 12:13
Цитата

Странно...
А что у вас в функции "progress"?

Там вывод информации, вот он там что то пытаеться вывести того, чего нету уже...
Цитата

Код

 if Terminated then
    begin
        break;
     end;

стоит в самом конце функции. Какой толк от этого? Циклов у вас не наблюдается. Хотя может вы не весь код привели...

Это не весь код, это в середине, а в начале там всякие переменные присваиваються и т.д.

Автор: artsb 9.1.2010, 12:20
Цитата(ZBugz @  9.1.2010,  12:13 Найти цитируемый пост)
Это не весь код

Так давайте весь smile Ну или почти весь.

Автор: ZBugz 9.1.2010, 12:50
Цитата(artsb @ 9.1.2010,  12:20)
Цитата(ZBugz @  9.1.2010,  12:13 Найти цитируемый пост)
Это не весь код

Так давайте весь smile Ну или почти весь.

Ну все тоже самое smile 

Код

procedure TCopyThread.Execute;
begin
  Zader:=TTimer.Create(Mainform);
  Zader.Enabled:=True;
  Zader.OnTimer:=OnTimerProc;
  Zader.Interval:=RefreshR1;
//чето делаем
try
//чето делаем
Application.ProcessMessages;
 if Terminated then
    begin
       zader.Free;      
       break;
     end;
    except
      MyError(Exception(ExceptObject));
    end
  finally
   Synchronize(Stop);
end;

constructor TCopyThread.Create(Suspended: boolean; );
begin
  inherited Create (Suspended);
  LineIndex:= ILineIndex;
end;

procedure TCopyThread.OnTimerProc(Sender: TObject);
begin
  Synchronize(Progress);
end;

procedure TCopyThread.Progress;
begin
// чето делаем
end;

Synchronize(Progress) идет через таймер, что бы ниче при отображении не мигало. Я подозреваю его, хотя что free, что destroy, пофигу, все равно отрабатывает Synchronize(Stop), а в то же время поток еще Synchronize(Progress)

Добавлено через 6 минут и 3 секунды
Причем щас прошелся еще раз дебагером, выходит Synchronize(Stop), все там делает, а потом как все там прошел, уходит в Synchronize(Progress)  smile 

Это как ?  smile 

Автор: artsb 9.1.2010, 13:12
ИМХО лучше так:
Код

  Zader.OnTimer:=OnTimerProc;
  Zader.Interval:=RefreshR1;
 Zader.Enabled:=True; // <- сюда

И что-то не видно Stream...

Автор: ZBugz 9.1.2010, 13:55
Цитата

ИМХО лучше так:
Код

  Zader.OnTimer:=OnTimerProc;
  Zader.Interval:=RefreshR1;
 Zader.Enabled:=True; // <- сюда


Ну да, чето не заметил smile
Цитата

И что-то не видно Stream...
А там другое. Это как пример был.

Автор: artsb 9.1.2010, 14:38
Цитата(ZBugz @  9.1.2010,  13:55 Найти цитируемый пост)
А там другое. Это как пример был. 


ZBugz, ты меня запутал smile Покажи плиз кусок с ошибкой и опиши что именно не так. Ну или выложи проект...

Автор: ZBugz 9.1.2010, 14:49
Цитата(artsb @ 9.1.2010,  14:38)
Цитата(ZBugz @  9.1.2010,  13:55 Найти цитируемый пост)
А там другое. Это как пример был. 


ZBugz, ты меня запутал smile Покажи плиз кусок с ошибкой и опиши что именно не так. Ну или выложи проект...

Дык нету ошибки явной. 
Смысл вот в чем, все работает, берешь удаляешь данные из ячейки listview, передаю терминэйт, а так как уже после терминэйт все free, то вывод данных в ячейку падает в ошибку.... Их брать то уже негде... smile Уже все free сделали и пропали, а поток при этом все хочет инфу вывести на VCL компонет.

Кстати, почитал я, так вот, такое часто, к примеру, при копировании файла. Так вот у меня именно тоже самое что и тут http://forum.vingrad.ru/forum/topic-60076/anchor-entry480375/0.html
Тока в этой статье ничерта не понятно как реализовать остановку  smile 

Автор: ZBugz 9.1.2010, 19:52
Тут пришел мой начальник smile И сказал, что делать таймер в потоке, это бред, потому что таймер в потоках живет криво. Это я уберу, у меня так и так было без таймера в свое время...
Далее, кое че подправил, читая статью про потоки, все почти работает. Смысл в том что действительно, делая файловые операции в потоки, это жесть, в плане отловки закрытия файлов, поток потоком, а файловые операции, это лперации... Ими управляет система.

Автор: Демо 9.1.2010, 23:35
Цитата(ZBugz @  9.1.2010,  19:52 Найти цитируемый пост)
Тут пришел мой начальник  И сказал, что делать таймер в потоке, это бред, потому что таймер в потоках живет криво. 


Это не бред, и живёт таймер в потоках весьма хорошо. Бред - эта цитата.

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

>Автор

Как я выше написал, чтобы дождаться окончания выполнения поточной функции, в Delphi есть метод TThread.WaitFor.

Твоя нить  при установке флага Terminated должна немедленно закончить работу.
Непонятно, в чём у тебя проблема.

Цитата(ZBugz @  9.1.2010,  12:50 Найти цитируемый пост)
Synchronize(Progress) идет через таймер, что бы ниче при отображении не мигало. Я подозреваю его, хотя что free, что destroy, пофигу, все равно отрабатывает Synchronize(Stop), а в то же время поток еще Synchronize(Progress)Добавлено через 6 минут и 3 секундыПричем щас прошелся еще раз дебагером, выходит Synchronize(Stop), все там делает, а потом как все там прошел, уходит в Synchronize(Progress)   Это как ?   


А не судьба проверить установку флага Terminated везде, где это может повлиять на работу приложения?

Автор: ZBugz 10.1.2010, 13:22
Цитата

Это не бред, и живёт таймер в потоках весьма хорошо. Бред - эта цитата.

Значит таймер может быть рожденный в потоке и жить хорошо ?

Цитата

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

А как тогда быть ? Вообще убрать ?
Цитата

Как я выше написал, чтобы дождаться окончания выполнения поточной функции, в Delphi есть метод TThread.WaitFor.

Я не пойму как ее использовать  smile 
Цитата

Твоя нить  при установке флага Terminated должна немедленно закончить работу.
Непонятно, в чём у тебя проблема.

Так она и вроде как и заканчивает работу.
Цитата

А не судьба проверить установку флага Terminated везде, где это может повлиять на работу приложения?

Я сделал это, в одном месте (проверку в TCopyThread.Progress, все хорошо), но проблема именно в том, что сам windows не успевает закрыть файлы или ему антивирус мешает и т.д. , поэтому получаеться что я пытаюсь открыть еще не закрытый файл...

Автор: Демо 10.1.2010, 13:42
Цитата(ZBugz @  10.1.2010,  13:22 Найти цитируемый пост)
Значит таймер может быть рожденный в потоке и жить хорошо ?


Вполне;)


Цитата(ZBugz @  10.1.2010,  13:22 Найти цитируемый пост)
А как тогда быть ? Вообще убрать ?


ни в коем случае не используй эту функцию в дополнительных потоках.


Цитата(ZBugz @  10.1.2010,  13:22 Найти цитируемый пост)
Я не пойму как ее использовать 


Вот смотри:

В реализации TThread устанавливаешь FreeOnTerminated := False;

В коде, где у тебя нужно дождаться завершения потока:

Код

MyThread.WaitFor;
MyThread.Free;


После выполнения этого кода у тебя гарантированно отработал деструктор потока.


Цитата(ZBugz @  10.1.2010,  13:22 Найти цитируемый пост)
Я сделал это, в одном месте (проверку в TCopyThread.Progress, все хорошо), но проблема именно в том, что сам windows не успевает закрыть файлы или ему антивирус мешает и т.д. , поэтому получаеться что я пытаюсь открыть еще не закрытый файл...



Попробуй код из предыдущего абзаца. Если ошибка останется, значит всё же логическая ошибка где-то в другом месте.

Автор: artsb 10.1.2010, 14:12
Цитата(Демо @  10.1.2010,  13:42 Найти цитируемый пост)
В коде, где у тебя нужно дождаться завершения потока:


Демо, ZBugz хочет сделать эту проверку в самом потоке (в функции Execute), если я правильно понял  smile 
Ну и это
Код

MyThread.Free;

Будет там не в тему.

Если честно, я до сих пор не могу понять что и где работает не так  smile 

Автор: Демо 10.1.2010, 14:31
Цитата(artsb @  10.1.2010,  14:12 Найти цитируемый пост)
Демо, ZBugz хочет сделать эту проверку в самом потоке (в функции Execute), если я правильно понял   Ну и этокод Pascal/Delphi1:MyThread.Free;highlightSyntax('delphi_NGZkMW','delphi');Будет там не в тему.


Дык перечитай топик-)
Terminate для завершения потока и используется.


Цитата(artsb @  10.1.2010,  14:12 Найти цитируемый пост)
Если честно, я до сих пор не могу понять что и где работает не так  


У автора секретная программа smile 

Автор: artsb 10.1.2010, 14:56
Цитата(Демо @  10.1.2010,  14:31 Найти цитируемый пост)
Terminate для завершения потока и используется.

Эмм... Насколько я понял, топикстартер хочет делать эту проверку именно после проверки флага Terminated. Или до меня опять не дошло  smile 

Автор: ZBugz 10.1.2010, 16:53
Цитата

Вполне;)

Тогда пока оставлю smile
Цитата

ни в коем случае не используй эту функцию в дополнительных потоках.

Завтра попробую без не, впринципе мысль была, что впринципе нафиг там не нужно это.
Цитата

Вот смотри:

В реализации TThread устанавливаешь FreeOnTerminated := False;

В коде, где у тебя нужно дождаться завершения потока:

Код

MyThread.WaitFor;
MyThread.Free;


Я нечно пробывал, но у меня ошибки получались. Завтра еще попробую, отпишусь.

Цитата

Попробуй код из предыдущего абзаца. Если ошибка останется, значит всё же логическая ошибка где-то в другом месте.

Да все хорошо. Я понял почему ошибка, отловил, не страшно.

Добавлено @ 16:54
Цитата(artsb @ 10.1.2010,  14:56)
Эмм... Насколько я понял, топикстартер хочет делать эу проверку именно после проверки флага Terminated. Или до мня опять не дошло  smile

Ага, именно после проверки, послал Terminated и жду пока он 100% убьеться поток.

Добавлено через 3 минуты и 54 секунды
Цитата(Демо @ 10.1.2010,  14:31)
У автора секретная программа smile

Ага  smile 

Автор: artsb 10.1.2010, 17:02
Цитата(ZBugz @  10.1.2010,  16:53 Найти цитируемый пост)
попробую без не

И действительно. Я что-то внимания не обратил.
ProcessMessages, насколько мне известно, служит для "насильной" обработки пришедших сообщений, которые не могут обработаться при выполнении ёмкой операции. Это, например, перерисовка формы, перемещение формы и т.п.
А вы пытаетесь вызвать её из потока, которому эти сообщения и даром не нужны.

Автор: ZBugz 11.1.2010, 10:25
Я почитал, что ProcessMessages надо юзать тогда, когда ты выводишь информацию на контролы, но если пользуешь синхронайз, то он нафиг не нужен вообще.

Автор: artsb 11.1.2010, 10:36
Из справки:
Цитата

Interrupts the execution of an application so that it can process the message queue.

void __fastcall ProcessMessages(void);

Description

Call ProcessMessages to permit the application to process messages that are currently in the message queue. ProcessMessages cycles the Windows message loop until it is empty, and then returns control to the application.

Автор: ZBugz 11.1.2010, 17:23
Короче убрал я ProcessMessages и Timer. Demo помог. Ошибки почти все пропали. С таймером тяжко все таки в моем случае...

Автор: ZBugz 8.2.2010, 16:55
Ну короче новая проблема  smile 
Обрабатываю все в TCopyThread.Destroy
А можно ли в TCopyThread.Destroy обрабатывать визульные компоненты ? Т.е. вызывать там всякие удаление ячеек и т.д. без синхронайз ?

Автор: artsb 8.2.2010, 16:59
Цитата(ZBugz @  8.2.2010,  16:55 Найти цитируемый пост)
А можно ли в TCopyThread.Destroy обрабатывать визульные компоненты ?

ИМХО можно, но лучше не нужно.

Цитата(ZBugz @  8.2.2010,  16:55 Найти цитируемый пост)
без синхронайз

конечно же, нет.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)