![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Прервать выполнение потока (TThread) [D6, WinXP]
cheloveck © (2005-05-14 09:52:00)Работает поток продолжительное время и если закрыть программу до окончания работы потока то выходит ошибка (из потока формируется список TList
Synchronize(SynhroList)). Что лучше: дожидаться выполнения потока или прервать?
А если прервать то как безопасно это сделать (с проверкой на существование потока)?
Поток создается, на каждый случай формирования списка, так:
mFScaner := TFScaner.Create(True);
mFScaner.FreeOnTerminate := true;
mFScaner.Priority := tpNormal;
mFScaner.Resume;
Marser (2005-05-14 14:48:00) [1]
> evvcom © (14.05.05 14:40) [11] [Новое
>сообщение][Ответить]
>
> > Поэтотому нужно ввести в теле цикла дополнительную
>проверку
>> вроде if Terminated then Exit
>
> Ты забыл упомянуть несколько "если". В общем случае
> ЭТО совершенно не обязательно.
Ага. Только общий перерастает в частный частенько просто незаметно. Как однажды вышло у меня... Потому я и обратил внимание на причину этого - стандартная проверка в конце текущей итерации.
Style (2005-05-14 14:44:00) [2]
> сам по себе он нисколько не опасен.
> но если требуется некий контроль за работой потока после
> его создания через его же методы, и при этом не приняты
> никакие меры по уведомлению о завершении потока, то схлопотать
> AV в какой-то момент времени при обращении к св-ву/методу
> уже несуществующего объекта (ведь он сам себя разрушает
> !) - это запросто
Но это уже называется дикий указатель...
С таким же успехом можно убить поток и из какого-нибудь другого потока. А в треьем обратиться к указателю на уже не существующий, что возможно приведет к AV.
evvcom (2005-05-14 14:40:00) [3]
> Поэтотому нужно ввести в теле цикла дополнительную проверку
> вроде if Terminated then Exit
Ты забыл упомянуть несколько "если". В общем случае ЭТО совершенно не обязательно.
Digitman (2005-05-14 14:22:00) [4]
> Что может быть опасного во FreeOnTerminate
сам по себе он нисколько не опасен.
но если требуется некий контроль за работой потока после его создания через его же методы, и при этом не приняты никакие меры по уведомлению о завершении потока, то схлопотать AV в какой-то момент времени при обращении к св-ву/методу уже несуществующего объекта (ведь он сам себя разрушает !) - это запросто
GuAV (2005-05-14 14:07:00) [5]
> Что может быть опасного во FreeOnTerminate
То что после присвоения этого флага с переменной класса потока манипуляции [4] так же как и другие манипуляции могут привести к непредсказуемым последствиям, т.к. поток может сам себя освободить после завершения, а завершится он может уже до выполнения этих манипуляций.
Если в конструкторе потока св-ву FreeOnTerminate присваивается True, то не следует вообще объявлять переменную класса потока. Т.е. не Thread := TmyThd.Create; , а просто TmyThd.Create;
Разуеется, если поток гарантированно не завершится до выполнения определённого условия, то можно использовать переменную класса потока до выполнения этого условия, но imho проще не использовать FreeOnTerminate в этом случае.
Style (2005-05-14 12:12:00) [6]
Digitman © (14.05.05 11:04) [6]
FreeOnTerminate = True в ряде его применений - опасный подход к уничтожению трэд-объектов
я бы рекомендовал не взводить этот флаг, а просто в нужный момент ЯВНО вызывать Thread.Free, при условии что алгоритм в теле Execute корректно реагирует на состояние флага Terminated
Что может быть опасного во FreeOnTerminate
все равно в итоге вызывается.
if FreeThread then Thread.Free;
Причем не из самого класса, а из глобальной процедуры потока???
Marser (2005-05-14 11:58:00) [7]
> novice_man © (14.05.05 10:52) [5] [Новое
>сообщение][Ответить]
> спасибо
Нужно помнить, что Terminate всего лишь устанавливает Terminated. Обычно тело потока устроено так: repeat..until Terminated, то есть проверка и завершение произойдут только в конце текущей итерации цикла. Поэтотому нужно ввести в теле цикла дополнительную проверку вроде if Terminated then Exit
Digitman (2005-05-14 11:04:00) [8]
> novice_man © (14.05.05 10:08) [3]
пример в [4] c учетом FreeOnTerminate = True чреват "граблями".
ибо нет никакой гарантии, что на момент Thread.WaitFor объект еще существует - он вполне мог быть уже и уничтожен в период времени между Thread.Terminate и Thread.WaitFor
FreeOnTerminate = True в ряде его применений - опасный подход к уничтожению трэд-объектов
я бы рекомендовал не взводить этот флаг, а просто в нужный момент ЯВНО вызывать Thread.Free, при условии что алгоритм в теле Execute корректно реагирует на состояние флага Terminated
novice_man (2005-05-14 10:52:00) [9]спасибо
Style (2005-05-14 10:12:00) [10]Thread.Terminate;
Thread.WaitFor;
Thread.Free;
novice_man (2005-05-14 10:08:00) [11]Digitman © (14.05.05 10:02) [2]
Как выполнить ожидание завершение потока в программе?
Digitman (2005-05-14 10:02:00) [12]
> Что лучше: дожидаться выполнения потока или прервать?
лучше если доп.поток самостоятельно завершит свое выполнение по команде основного потока.
а чтобы он это сделал как можно быстрее, в методе TThread.Execute можно циклически и как можно чаще проверять состояние флага TThread.Terminated (при создании доп.потока он сброшен и будет взведен как только какой-либо поток вызовет метод TThread.Terminate), и как только будет обнаружено взведенное состояние флага немедленно завершать выполнение цикла с последующим завершением работы TThread.Execute
Style (2005-05-14 09:56:00) [13]TerminateThread?