Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Вниз

Как корректно удалить экземпляр TThread из TList?   Найти похожие ветки 

 
DVM ©   (2010-05-13 00:09) [40]


> Игорь Шевченко ©   (13.05.10 00:05) [37]


> Очевидно глючности конструкции FreeOnTerminate = true, вроде
> речь шла об этом.

Речь не о глючности конструкции, а о ее глюконосности. Разные вещи.


 
DVM ©   (2010-05-13 00:12) [41]


> kotyara12   (13.05.10 00:05) [38]

я не понимаю, зачем тебе все эти пляски с бубном вокруг FreeOnTerminate = true, когда Terminate + WaitFor + FreeOnTerminate = false позволяют прекрасно все контролировать? Один хрен у тебя есть список.


 
Игорь Шевченко ©   (2010-05-13 00:12) [42]

DVM ©   (13.05.10 00:07) [39]


> Лучше бы кто нибудь мне привел реальную пользу от FreeOnTerminate


ну давай я тебе длинно и непоследовательно расскажу про задачи своей предметной области, про алгоритмы их решения, возможную реализацию этих алгоритмов, и в качестве одной из наглядных иллюстраций будет конструкция с несколькими дополнительными потоками, у которых свойство FreeOnTerminate установлено в True. Ты это сочтешь за реальную пользу или без рассказа поверишь на слово ?

Польза простая - выстрелил, забыл, оно дальше само полетело и поразило.


 
Игорь Шевченко ©   (2010-05-13 00:14) [43]

DVM ©   (13.05.10 00:09) [40]


> Речь не о глючности конструкции, а о ее глюконосности. Разные
> вещи.


Я понял, considered harmhul. А в Борландовских Demos об этом не знали. Изучайте Demos - источник знаний.


 
kotyara12   (2010-05-13 00:15) [44]


> 3) Мы можем корректно закрыть все ресурсы потоков и сами
> потоки и затем уничтожить объекты TThread просто вызовом
> Terminate и WaitFor.


WaitFor уничтожит поток?


 
DVM ©   (2010-05-13 00:19) [45]


> Игорь Шевченко ©   (13.05.10 00:12) [42]


> Польза простая - выстрелил, забыл, оно дальше само полетело
> и поразило.

Наверное оно так. Пока программа работает и закрываться не собирается. Но вот она собралась закругляться. И что у нас там летает контролировать сложно. Хорошо если оно там умрет своей смертью вовремя без последствий.

Не, как хотите, но такой подход не по мне.


 
Eraser ©   (2010-05-13 00:20) [46]

> [44] kotyara12   (13.05.10 00:15)

нет, потом еще Free нужно вручную.


 
kotyara12   (2010-05-13 00:21) [47]


> я не понимаю, зачем тебе все эти пляски с бубном вокруг
> FreeOnTerminate = true, когда Terminate + WaitFor + FreeOnTerminate
> = false позволяют прекрасно все контролировать? Один хрен
> у тебя есть список.

да к тому, что тогда нужно поток по завершнию работы (нормальному завершению в точ числе и в основном) удалить из памяти.
запускаю я поток, он выполняет свою задачу, в обработчике OnTerminate - удаляет себя из списка. А в памяти он останется. И в OnTerminate делать Sender.Free я думаю некорректно.
Terminate + WaitFor нужен только для завершения работы сервиса. а сервис должен крутиться месяцы напролет


 
Eraser ©   (2010-05-13 00:21) [48]

> [39] DVM ©   (13.05.10 00:07)


> Лучше бы кто нибудь мне привел реальную пользу от FreeOnTerminate

любой многопоточный сервер, например, named pipe.


 
DVM ©   (2010-05-13 00:21) [49]


> kotyara12   (13.05.10 00:15) [44]


> WaitFor уничтожит поток?

нет

Последовательность такова:

1) Teminate - сообщаем потоку чтобы он закруглялся. Он должен закругляться по этому сигналу, постоянно проверяя этот флаг.

2) WaiFor - ждем пока поток закруглится. Если он не сможет, то мы висим!

3) Free объекту потока. Теперь можно точно и со спокойной душой.


 
DVM ©   (2010-05-13 00:23) [50]


> Eraser ©   (13.05.10 00:21) [48]


> любой многопоточный сервер

не лучше ли держать пулы потоков и не тормошить систему постоянно их созданием уничтожением?


 
kotyara12   (2010-05-13 00:25) [51]

а не проще, если он сам себя удалит. а в 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;


 
Eraser ©   (2010-05-13 00:26) [52]

> [50] DVM ©   (13.05.10 00:23)

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


 
kotyara12   (2010-05-13 00:29) [53]


> не лучше ли держать пулы потоков и не тормошить систему
> постоянно их созданием уничтожением?

не думаю. по времени потоки будут создаваться через большие промежутки времени. да и выполнение в среднем будет занимать несколько часов.
к тому же пул нужно еще разобраться как реализовать - я попробовал понять как работат пул у TcpServer - мало чего понял с наскоку.


 
DVM ©   (2010-05-13 00:30) [54]


> kotyara12   (13.05.10 00:25) [51]

Ты главное не теряй контроль над списком, а как удалять из списка дело десятое. Главное, чтобы в списке не оказалось дохлых ссылок и случайно не произошло обращения по дохлой ссылке.


 
kotyara12   (2010-05-13 00:33) [55]

ну да ладно, завтра продолжим "тренироваться".. еще раз всем спасибо...
зы: все равно дома sql базы нет - пробовать не на чем, а тестовый пример лепить лень.


 
Игорь Шевченко ©   (2010-05-13 00:44) [56]

DVM ©   (13.05.10 00:19) [45]


>  Пока программа работает и закрываться не собирается. Но
> вот она собралась закругляться. И что у нас там летает контролировать
> сложно. Хорошо если оно там умрет своей смертью вовремя
> без последствий.


Как ты понимаешь, при завершении первичного потока процесса, автоматически завершаются все дополнительные потоки в этом процессе.


 
sniknik ©   (2010-05-13 02:15) [57]

блин, во у вас тут пляски с бубном...
если бы хотел уничтожить кучу потоков, с обязательным "своим"  контролем, то сделал бы так

  for i := 0 to Count - 1 do
    Item[i].Terminate;

  while ThreadCount > 0  do
   Sleep(10);

  for i := 0 to Count - 1 do
    Item[i].Free


ну и, понятно в начале execute ThreadCount+1 в конце  ThreadCount-1. и все.
мало того мороки меньше так еще и сработать в сумме должно быстрее, чем персональное ожидание завершения каждого потока (одному больше на это времени нужно другому меньше, так не "времена" не будут складываться, а будет примерно равно одному - максимальному).


 
sniknik ©   (2010-05-13 02:18) [58]

кстати пример потоков в дельфе (ну тот который пример сортировок) именно так и делает, насколько помню.


 
Германн ©   (2010-05-13 02:30) [59]


> sniknik ©   (13.05.10 02:15) [57]
>
> блин, во у вас тут пляски с бубном...
>

Тут, имхо, пляшут не только Фома с Ерёмой. Тут скорее хоровод группы, каждый из которой, пляшет свой танец.
Но у всех них есть общее. Они пляшут под музыку Дельфи.
Некоторые ещё умудряются плясать под две музыки сразу. Но жалуются на сложности такой пляски.
:)


 
Leonid Troyanovsky ©   (2010-05-13 07:33) [60]


> antonn ©   (12.05.10 23:18) [11]

> там Synchronize() случаем не нужен?

The OnTerminate event handler is called in the context of the main VCL thread

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2010-05-13 07:42) [61]


> Eraser ©   (12.05.10 23:23) [13]

> кстати, всегда интересовал такой вопрос - где правильно
> уничтожать дескриптор созданного через Begin/CreateThread
> потока? )

Тогда, когда хендл стал более не нужен.
Можно хоть сразу после BeginThread.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2010-05-13 07:57) [62]


> Игорь Шевченко ©   (13.05.10 00:44) [56]

> Как ты понимаешь, при завершении первичного потока процесса,

Это не всегда так. Попробуй пустить вторичный поток,
а первичному сделать ExitThread.

У Рихтера, да и в мсдн, есть условия завершения процесса (лень искать).
Одно из них: завершение при завершении последнего потока, ЕМНИП.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2010-05-13 07:59) [63]


> Rouse_ ©   (12.05.10 23:31) [20]

> Имеется ввиду через апи TerminateThread()

Чего мелочиться: TerminateProcess.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2010-05-13 08:01) [64]


> Loginov Dmitry ©   (12.05.10 23:35) [27]

> Лобовой метод обхода

Военная мудрость? :)

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2010-05-13 08:07) [65]


> kotyara12   (13.05.10 00:29) [53]

> к тому же пул нужно еще разобраться как реализовать

http://rsdn.ru/?article/baseserv/threadpool.xml

И еще статью by Alex Fedotov
http://rsdn.ru/?summary/2393.xml

--
Regards, LVT.


 
Rouse_ ©   (2010-05-13 10:25) [66]


> Loginov Dmitry ©   (12.05.10 23:45) [34]
> С того, что поток в этот момент занят записью какого-нибудь
> файла на жесткий диск.

И чего? Ты что не знаешь какой у тебя поток что делает и какой из них можно спокойно терминировать, а какой гарантированно висит в дедлоке? Ну-ну.
Если ПО чего-то пишет там на диск причем так, что при выключении компа оно не вырубается и мешает нормальной перезагрузке машины (ну пишет-же, чего его тревожат), то мне абсолютно пофиг на мнение разработчика данного ПО о корректности применения терминирования нити через АПИ ибо он моментально переносится в разряд криворуких и само ПО сносится с машины как класс. Помниться устанавливал я на свои машину парочку таких экземпляров - все в итоге оказались в корзине.


> DVM ©   (13.05.10 00:07) [39]
> 1) Мы всегда знаем, сколько у нас живых экземляров объекта
> TThread
> 2) Мы всегда можем быть уверены в том что в конкретный момент
> конкретный экземпляр жив.
> 3) Мы можем корректно закрыть все ресурсы потоков и сами
> потоки и затем уничтожить объекты TThread просто вызовом
> Terminate и WaitFor.

Чушь. Даже при включенном FreeOnTerminate мы спокойно выполняем первый и второй пункты. А третий пункт вообще ни о чем. Вот тебе пример - нить делает NtQueryObject на синхронном пайпе - я посмотрю как ты корректно завершишь такую нить.


> Лучше бы кто нибудь мне привел реальную пользу от FreeOnTerminate

А реальную пользу я тебе написал еще в [10], но ты по всей видимости пропустил этот момент.


 
Игорь Шевченко ©   (2010-05-13 10:57) [67]

Leonid Troyanovsky ©   (13.05.10 07:57) [62]


> Это не всегда так. Попробуй пустить вторичный поток,
> а первичному сделать ExitThread.


В этом случае процесс не завершается. Но тут такой момент - при завершении первичного потока вызывается не ExitThread, а ExitProcess


 
Leonid Troyanovsky ©   (2010-05-13 11:38) [68]


> Игорь Шевченко ©   (13.05.10 10:57) [67]

> - при завершении первичного потока вызывается не ExitThread,
>  а ExitProcess

Если оную не вызвал вторичный поток ;)

--
Regards, LVT.


 
Eraser ©   (2010-05-13 13:57) [69]

> [61] Leonid Troyanovsky ©   (13.05.10 07:42)

интересное замечание. когда-то давно были с этим грабли, по всей видимости из-за кривизны рук, но в мозгу отложился, как оказалось, ошибочный вывод, что нужно дожидаться окончания выполнения потока перед закрытием дескриптора. возможно теперь BeginThread будет использоваться чаще ;-)


 
DVM ©   (2010-05-13 15:41) [70]


> Rouse_ ©   (13.05.10 10:25) [66]


> Даже при включенном FreeOnTerminate мы спокойно выполняем
> первый и второй пункты.

Выполнять то выполняем, но не кажется ли что при этом теряется все преимущество FreeOnTerminate := True - запустил и забыл?


 
DVM ©   (2010-05-13 15:44) [71]


> Rouse_ ©   (13.05.10 10:25) [66]


> А третий пункт вообще ни о чем.

Третий пункт как раз на случай завершения приложения - проходим по списку убиваем.


> Rouse_ ©   (13.05.10 10:25) [66]


> Вот тебе пример - нить делает NtQueryObject на синхронном
> пайпе - я посмотрю как ты корректно завершишь такую нить.
>

Так эта...может в архитектуре надо что-то подправить, чем разбрасываться TerminateThread?


 
RWolf ©   (2010-05-13 15:51) [72]

> Rouse_ ©   (13.05.10 10:25) [66]

> Даже при включенном FreeOnTerminate мы спокойно выполняем
> первый и второй пункты.


каким образом, кстати?
экземпляры класса TMySuddenlyTerminatingThread могут стать недоступны в любой момент, значит, как-то по-другому; а как?


 
DVM ©   (2010-05-13 15:53) [73]


> Вот тебе пример - нить делает NtQueryObject на синхронном
> > пайпе - я посмотрю как ты корректно завершишь такую нить.

Я сталкивался с аналогичной ситуацией, только были не пайпы, а сокеты в блокирующем режиме. Поток висел на connect() по 20 секунд и не было никакой возможности прервать поток.

Тогда же я на этом форуме высказал предположение о том, а хорошо ли будет использовать TerminateThread для быстрого выхода из приложения и прибивания таких потоков. Моментально был обруган уже не помню кем.
В результате был "изобретен" неблокирующий connect() для блокирующих сокетов.

Можно и в тупом цикле зависнуть - это не оправдание.


 
RWolf ©   (2010-05-13 15:53) [74]

и ещё интересен момент — кем и как будут завершаться эти созданные и забытые потоки при закрытии приложения?


 
DVM ©   (2010-05-13 15:54) [75]


> RWolf ©   (13.05.10 15:51) [72]


> значит, как-то по-другому; а как?

изобретаем синхронизированные велосипеды, о чем я и говорил. Смысл и преимущества все теряются.


 
Rouse_ ©   (2010-05-13 15:59) [76]


> экземпляры класса TMySuddenlyTerminatingThread могут стать
> недоступны в любой момент, значит, как-то по-другому; а
> как?

Перекрывая соответствующий обработчик мы избежим ситуации что они станут недоступны в любой момент :)


> DVM ©   (13.05.10 15:44) [71]
> Третий пункт как раз на случай завершения приложения - проходим
> по списку убиваем.

Ну не убьеш ты в сервисе, зависнешь на попытке синхронизации с основным потоком который стоит в суспенде :)


> DVM ©   (13.05.10 15:41) [70]
> Выполнять то выполняем, но не кажется ли что при этом теряется
> все преимущество FreeOnTerminate := True - запустил и забыл?

Вот именно - это единственное преимущество данного класса - именно запустил и забыл, все остальное гораздо качественнее и прозрачнее делается через апи, поэтому я использую класс TThread именно только в таких случаях, когда мне не нужно контролировать время его никчемной жыздни :)


 
DVM ©   (2010-05-13 16:03) [77]


> Rouse_ ©   (13.05.10 15:59) [76]


> Ну не убьеш ты в сервисе, зависнешь на попытке синхронизации
> с основным потоком который стоит в суспенде :)

Хм. Я может чего то недопонимаю, но вот именно так я делал как то и ничего не висло.


 
Rouse_ ©   (2010-05-13 16:04) [78]


> DVM ©   (13.05.10 15:44) [71]
> Так эта...может в архитектуре надо что-то подправить, чем
> разбрасываться TerminateThread?

Не вопрос - я с радостью выслушаю предложение по доработке вот этого примера с пересмотром архитектуры :)
http://rouse.drkb.ru/winapi.php#enumopenfiles


 
Rouse_ ©   (2010-05-13 16:06) [79]


> DVM ©   (13.05.10 16:03) [77]
> Хм. Я может чего то недопонимаю, но вот именно так я делал
> как то и ничего не висло.

Сервис конечно-же апишный ибо я про него говрю?
т.е. без использования всякого ненужно мусора в виде VCL-ного сервиса? :)


 
RWolf ©   (2010-05-13 16:09) [80]

> Rouse_ ©   (13.05.10 15:59) [76]

> не убьеш ты в сервисе, зависнешь на попытке синхронизации
> с основным потоком который стоит в суспенде :)


thd.Terminate;
thd.Resume;
//тут поток просыпается, видит, что его завершают, и выходит из Execute
thd.WaitFor;


> остальное гораздо качественнее и прозрачнее делается через
> апи


то есть через TerminateThread?
Выдержка из MSDN:

TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
* If the target thread owns a critical section, the critical section will not be released.
* If the target thread is allocating memory from the heap, the heap lock will not be released.
* If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread’s process could be inconsistent.
* If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL



Страницы: 1 2 3 вся ветка

Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.63 MB
Время: 0.073 c
2-1267379618
Pavel
2010-02-28 20:53
2010.08.27
Загрузка данных из файла в поток


2-1267885769
Mer01
2010-03-06 17:29
2010.08.27
Как задать массив Record при инициализации?


15-1271830825
12
2010-04-21 10:20
2010.08.27
Apache2.2. Странный глюк


15-1270758602
Юрий
2010-04-09 00:30
2010.08.27
С днем рождения ! 9 апреля 2010 пятница


15-1265491802
Юрий
2010-02-07 00:30
2010.08.27
С днем рождения ! 7 февраля 2010 воскресенье





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский