![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как корректно удалить экземпляр TThread из TList? [D7]
kotyara12 © (2010-05-12 21:22:00)Может и друрацкий вопрос, но я уже совсем запутался: я создаю несколько независимых потоков с FreeOnTerminate = True и помещаю их в экземпляр TList. Что произойдет, если поток отработает до конца и удалиться из памяти? Произойдет ли при этом удаление соответствущего указателя из TList или нужно как-то по другому удалить отработавший поток?
Loginov Dmitry (2010-05-12 23:45:00) [61]
> > Убивать потоки принудительно через TerminateThread() недопустимо.
>
> >
>
> При завершении приложения? С чего бы это?
С того, что поток в этот момент занят записью какого-нибудь файла на жесткий диск. Убъешь поток, получишь пол-файла или вообще ничего.
DVM (2010-05-12 23:42:00) [62]
> Rouse_ © (12.05.10 23:38) [30]
> При завершении приложения? С чего бы это?
Не, я не про завершение конечно. Хотя...
Я привык и при завершении пытаться все по-человечески все закрывать.
Loginov Dmitry (2010-05-12 23:41:00) [63]
> Имеется ввиду через апи TerminateThread()
Превосходный совет, нет слов :)
> Проблема то не в самом FreeOnTerminate = True, а в том,
> что его применение без особой на то необходимости и без
> тщательного контроля происходящего принесет только проблемы.
> Есть некоторая неочевидность того, что происходит при его
> применении и как пользоваться этим свойством.
Тут вроде как всего 2 варианта: либо мы ставим FreeOnTerminate = False, и отвечаем на уничтожение, либо ставим FreeOnTerminate = True, и дальше ни коем образом к объекту потока не обращаемся (ибо он может оказаться уничтожен в любой момент). Кстати да, есть поводы для глюков, как и со Suspend. Может подать идейку чтоб и FreeOnTerminate сделали deprecated =)
Rouse_ (2010-05-12 23:39:00) [64]
> Eraser © (12.05.10 23:37) [29]
> так и не чего синхронайз использовать, imho. за редчайшим
> исключением можно обойтись без него
Я бы кнечто тоже за, но ты реальзацию метода WaitFor смотрел? :)
Особливо вызов метода CheckSynchronize в рамках сервиса?
Rouse_ (2010-05-12 23:38:00) [65]
> DVM © (12.05.10 23:36) [28]
>
> Убивать потоки принудительно через TerminateThread() недопустимо.
>
При завершении приложения? С чего бы это?
И кстати, ты так и не привел аргументов в пользу отсутствия FreeOnTerminate
Eraser (2010-05-12 23:37:00) [66]> [26] DVM © (12.05.10 23:35)
кстати да, тут или FreeOnTerminate := true убрать, или WaitFor;
> [25] Rouse_ © (12.05.10 23:34)
так и не чего синхронайз использовать, imho. за редчайшим исключением можно обойтись без него и даже более грамотно выйдет.
DVM (2010-05-12 23:36:00) [67]Убивать потоки принудительно через TerminateThread() недопустимо.
Loginov Dmitry (2010-05-12 23:35:00) [68]
> пробовал. наткнулся на следующие грабли: при останвке сервиса
> останавливаю все потоки задач:
Правильно зависает. Зато ведь понятно из-за чего!
Лобовой метод обхода:
with fTaskList.LockList do
begin
try
for i := 0 to Count - 1 do
TThread(Item[i]).Terminate;
finally
fTaskList.UnlockList;
end
end;
while True do
begin
with fTaskList.LockList do
try
ACount := Count;
finally
fTaskList.UnlockList;
end;
if ACount = 0 then
Break
else
begin
Sleep(10);
//Application.ProcessMessages();
end;
end;
DVM (2010-05-12 23:35:00) [69]
> kotyara12 (12.05.10 23:27) [18]
> with fTaskList.LockList do
> begin
> try
> for i := 0 to Count - 1 do
> TThread(Item[i]).Terminate;
> TThread(Item[i]).WaitFor; <- ЗДЕСЬ ЗАВИСАЕТ НАМЕРТВО,
> приходится снимать процесс
> finally
> fTaskList.UnlockList;
> end
> end
Ты свое глюконосное FreeOnTerminate := true убери и не будет виснуть.
Rouse_ (2010-05-12 23:34:00) [70]
> дождаться завершения потока через WaitFor.
Не получиться опять-же, дедлок из-за неочевидного механизма синхронизаии в очень многих случаях :)
Eraser (2010-05-12 23:33:00) [71]> [18] kotyara12 (12.05.10 23:27)
OnTerminate срабатывает? где в этот момент висит TThread(Item[i])?
kotyara12 (2010-05-12 23:32:00) [72]
> Rouse_ © (12.05.10 23:31) [20]
> Имеется ввиду через апи TerminateThread()
спс... щас покопаемся...
Eraser (2010-05-12 23:32:00) [73]> [15] Rouse_ © (12.05.10 23:24)
да, и потому FreeOnTerminate наше все, т.к. частенько контроль этих самых дескрипторов выливается в куда более не тривиальную задачу, чем сам код потока.
а в случае чего всегда можно FreeOnTerminate отключить, убрать обработчик OnTerminate и дождаться завершения потока через WaitFor.
ну собственно я это не вам рассказываю, а топикстартеру )
DVM (2010-05-12 23:31:00) [74]
> Rouse_ © (12.05.10 22:51) [7]
> Игорь Шевченко © (12.05.10 23:06) [8]
Аргументы чего я должен привести?
Проблема то не в самом FreeOnTerminate = True, а в том, что его применение без особой на то необходимости и без тщательного контроля происходящего принесет только проблемы. Есть некоторая неочевидность того, что происходит при его применении и как пользоваться этим свойством.
Rouse_ (2010-05-12 23:31:00) [75]Имеется ввиду через апи TerminateThread()
Rouse_ (2010-05-12 23:30:00) [76]В рамках сервиса так нельзя - будет дедлок. - Срывай через терминирование.
kotyara12 (2010-05-12 23:27:00) [77]
> Вместо TList в таких случаях следует использовать TThreadList
пробовал. наткнулся на следующие грабли: при останвке сервиса останавливаю все потоки задач:
with fTaskList.LockList do
begin
try
for i := 0 to Count - 1 do
TThread(Item[i]).Terminate;
TThread(Item[i]).WaitFor; <- ЗДЕСЬ ЗАВИСАЕТ НАМЕРТВО, приходится снимать процесс
finally
fTaskList.UnlockList;
end
end
Rouse_ (2010-05-12 23:24:00) [78]
> kotyara12 (12.05.10 23:23) [14]
>
>
> > Rouse_ ©
>
> это как раз и есть сервис...
Тогда ололо - готовь голову к шишкам от граблей :)
Loginov Dmitry (2010-05-12 23:24:00) [79]
> Что остается - остается только пресловутый FreeOnTerminate,
> который позволяет нам не заморачиваться на написание кода
> типа WaitForSingleObject, а просто создать нить - передать
> ей задачу и забыть.
Вот-вот, передать задачу и забыть. И этом вся прелесть!
Rouse_ (2010-05-12 23:24:00) [80]
> Eraser © (12.05.10 23:23) [13]
Ествесвенно по завершении оного :)