![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как корректно удалить экземпляр TThread из TList? [D7]
kotyara12 © (2010-05-12 21:22:00)Может и друрацкий вопрос, но я уже совсем запутался: я создаю несколько независимых потоков с FreeOnTerminate = True и помещаю их в экземпляр TList. Что произойдет, если поток отработает до конца и удалиться из памяти? Произойдет ли при этом удаление соответствущего указателя из TList или нужно как-то по другому удалить отработавший поток?
DVM (2010-05-13 00:30:00) [41]
> kotyara12 (13.05.10 00:25) [51]
Ты главное не теряй контроль над списком, а как удалять из списка дело десятое. Главное, чтобы в списке не оказалось дохлых ссылок и случайно не произошло обращения по дохлой ссылке.
kotyara12 (2010-05-13 00:29:00) [42]
> не лучше ли держать пулы потоков и не тормошить систему
> постоянно их созданием уничтожением?
не думаю. по времени потоки будут создаваться через большие промежутки времени. да и выполнение в среднем будет занимать несколько часов.
к тому же пул нужно еще разобраться как реализовать - я попробовал понять как работат пул у TcpServer - мало чего понял с наскоку.
Eraser (2010-05-13 00:26:00) [43]> [50] DVM © (13.05.10 00:23)
ну а если сервер не супер-загруженный, когда ни когда создается по потоку?
оно то конечно все можно реализовать, вопрос во времени и целесообразности. пул вообще может довольно хитрой штукой быть, особенно для новичков в проекте, вот и получим грабли опять же.
kotyara12 (2010-05-13 00:25:00) [44]а не проще, если он сам себя удалит. а в OnTerminate удалит свой линк из списка?
а при завершении сервиса наверное можно использовать метод предложенный Loginov Dmitry, правда я его мальнько переработал:
with fTaskList.LockList do
begin
try
for i := 0 to Count - 1 do
TThread(Items[i]).Terminate;
finally
fTaskList.UnlockList;
end;
end;
repeat
with fTaskList.LockList do
begin
try
TaskCount := Count;
finally
fTaskList.UnlockList;
end;
end;
if TaskCount > 0 then Sleep(10);
until TaskCount = 0;
DVM (2010-05-13 00:23:00) [45]
> Eraser © (13.05.10 00:21) [48]
> любой многопоточный сервер
не лучше ли держать пулы потоков и не тормошить систему постоянно их созданием уничтожением?
Eraser (2010-05-13 00:21:00) [46]> [39] DVM © (13.05.10 00:07)
> Лучше бы кто нибудь мне привел реальную пользу от FreeOnTerminate
любой многопоточный сервер, например, named pipe.
DVM (2010-05-13 00:21:00) [47]
> kotyara12 (13.05.10 00:15) [44]
> WaitFor уничтожит поток?
нет
Последовательность такова:
1) Teminate - сообщаем потоку чтобы он закруглялся. Он должен закругляться по этому сигналу, постоянно проверяя этот флаг.
2) WaiFor - ждем пока поток закруглится. Если он не сможет, то мы висим!
3) Free объекту потока. Теперь можно точно и со спокойной душой.
kotyara12 (2010-05-13 00:21:00) [48]
> я не понимаю, зачем тебе все эти пляски с бубном вокруг
> FreeOnTerminate = true, когда Terminate + WaitFor + FreeOnTerminate
> = false позволяют прекрасно все контролировать? Один хрен
> у тебя есть список.
да к тому, что тогда нужно поток по завершнию работы (нормальному завершению в точ числе и в основном) удалить из памяти.
запускаю я поток, он выполняет свою задачу, в обработчике OnTerminate - удаляет себя из списка. А в памяти он останется. И в OnTerminate делать Sender.Free я думаю некорректно.
Terminate + WaitFor нужен только для завершения работы сервиса. а сервис должен крутиться месяцы напролет
Eraser (2010-05-13 00:20:00) [49]> [44] kotyara12 (13.05.10 00:15)
нет, потом еще Free нужно вручную.
DVM (2010-05-13 00:19:00) [50]
> Игорь Шевченко © (13.05.10 00:12) [42]
> Польза простая - выстрелил, забыл, оно дальше само полетело
> и поразило.
Наверное оно так. Пока программа работает и закрываться не собирается. Но вот она собралась закругляться. И что у нас там летает контролировать сложно. Хорошо если оно там умрет своей смертью вовремя без последствий.
Не, как хотите, но такой подход не по мне.
kotyara12 (2010-05-13 00:15:00) [51]
> 3) Мы можем корректно закрыть все ресурсы потоков и сами
> потоки и затем уничтожить объекты TThread просто вызовом
> Terminate и WaitFor.
WaitFor уничтожит поток?
Игорь Шевченко (2010-05-13 00:14:00) [52]DVM © (13.05.10 00:09) [40]
> Речь не о глючности конструкции, а о ее глюконосности. Разные
> вещи.
Я понял, considered harmhul. А в Борландовских Demos об этом не знали. Изучайте Demos - источник знаний.
Игорь Шевченко (2010-05-13 00:12:00) [53]DVM © (13.05.10 00:07) [39]
> Лучше бы кто нибудь мне привел реальную пользу от FreeOnTerminate
ну давай я тебе длинно и непоследовательно расскажу про задачи своей предметной области, про алгоритмы их решения, возможную реализацию этих алгоритмов, и в качестве одной из наглядных иллюстраций будет конструкция с несколькими дополнительными потоками, у которых свойство FreeOnTerminate установлено в True. Ты это сочтешь за реальную пользу или без рассказа поверишь на слово ?
Польза простая - выстрелил, забыл, оно дальше само полетело и поразило.
DVM (2010-05-13 00:12:00) [54]
> kotyara12 (13.05.10 00:05) [38]
я не понимаю, зачем тебе все эти пляски с бубном вокруг FreeOnTerminate = true, когда Terminate + WaitFor + FreeOnTerminate = false позволяют прекрасно все контролировать? Один хрен у тебя есть список.
DVM (2010-05-13 00:09:00) [55]
> Игорь Шевченко © (13.05.10 00:05) [37]
> Очевидно глючности конструкции FreeOnTerminate = true, вроде
> речь шла об этом.
Речь не о глючности конструкции, а о ее глюконосности. Разные вещи.
DVM (2010-05-13 00:07:00) [56]
> Rouse_ © (12.05.10 23:38) [30]
> И кстати, ты так и не привел аргументов в пользу отсутствия
> FreeOnTerminate
1) Мы всегда знаем, сколько у нас живых экземляров объекта TThread
2) Мы всегда можем быть уверены в том что в конкретный момент конкретный экземпляр жив.
3) Мы можем корректно закрыть все ресурсы потоков и сами потоки и затем уничтожить объекты TThread просто вызовом Terminate и WaitFor.
Лучше бы кто нибудь мне привел реальную пользу от FreeOnTerminate
Игорь Шевченко (2010-05-13 00:05:00) [57]DVM © (12.05.10 23:31) [21]
> Аргументы чего я должен привести?
Очевидно глючности конструкции FreeOnTerminate = true, вроде речь шла об этом.
> Проблема .. в том,
> что его применение без особой на то необходимости и без
> тщательного контроля происходящего принесет только проблемы.
> Есть некоторая неочевидность того, что происходит при его
> применении и как пользоваться этим свойством.
У нас говорят проще: дай дураку член стеклянный, он и член разобьет, и руки порежет.
Какая нафиг неочевидность - открываешь classes.pas и все, как на ладони.
Потоками вообще надо слегка с умом пользоваться, там и без FreeOnTerminate хватает граблей.
kotyara12 (2010-05-13 00:05:00) [58]Спасибо всем за комментарии... начинаю понемногу въезжать в ситуацию.
Насколько я понял из реализации TThread обработка OnTerminate (например, удаление потока из списка) и FreeOnTerminate = True друг другу не мешают... А вызовfTaskList.Remove(Sender);из OnTerminate при FreeOnTerminate = False не уничтожит поток...
var
FreeThread: Boolean;
begin
try
if not Thread.Terminated then
try
Thread.Execute;
except
Thread.FFatalException := AcquireExceptionObject;
end;
finally
FreeThread := Thread.FFreeOnTerminate;
Result := Thread.FReturnValue;
Thread.DoTerminate; <- обработка OnTerminate
Thread.FFinished := True;
SignalSyncEvent;
if FreeThread then Thread.Free; <- FreeOnTerminate = True
или я ошибаюсь?
Loginov Dmitry (2010-05-12 23:52:00) [59]Самое надежное средство: BeginThread. Никогда не подводит :)
Eraser (2010-05-12 23:47:00) [60]> [31] Rouse_ © (12.05.10 23:39)
> Я бы кнечто тоже за, но ты реальзацию метода WaitFor смотрел?
> :)
ух, ну и накрутили же они, я то наивно пологал, что там честный WaitForSingleObject ;-)
оно кстати так и есть, если GetCurrentThreadID <> MainThreadID, что для сервиса чаще всего и бывает.
if GetCurrentThreadID = MainThreadID then
begin
WaitResult := 0;
H[1] := SyncEvent;
repeat
{ This prevents a potential deadlock if the background thread
does a SendMessage to the foreground thread }
if WaitResult = WAIT_OBJECT_0 + 2 then
PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
WaitResult := MsgWaitForMultipleObjects(2, H, False, 1000, QS_SENDMESSAGE);
CheckThreadError(WaitResult <> WAIT_FAILED);
if WaitResult = WAIT_OBJECT_0 + 1 then
CheckSynchronize;
until WaitResult = WAIT_OBJECT_0;
end else WaitForSingleObject(H[0], INFINITE);