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

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

Как корректно удалить экземпляр TThread из TList? [D7]


Страницы:   1 2 3 4 5

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);


Страницы:   1 2 3 4 5

Наверх

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