| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: WinAPI и системное программирование > Почему поток обрывается? |
| Автор: Dota 24.7.2010, 19:36 | ||
| Почему поток обрывается при закрытии главного окна и завершается приложение? Блин, где не читаю, везде пишут, что процесс завершится только тогда, когда завершится последний поток. А тут получается что то принудительно его завершает. Ситуация усложняется еще и тем, что потоки собираюсь создавать в DLL и программа, которая будет использовать DLL точно также может в любой момент обрываться и обрывается поток...
|
| Автор: CodeMonkey 24.7.2010, 21:09 |
| Потому что "end." в dpr файле - это вызов Halt(0). |
| Автор: Dota 25.7.2010, 21:25 |
| Спасибо. Теперь ясно, что не кошерно все устроено в этом плане. |
| Автор: CodeMonkey 25.7.2010, 23:45 | ||
Пффф. Будьте осторожны: ваши желания могут исполнится. И тогда вам это не понравится. Подумайте сами почему. xkor уже дал подсказку.
И с неслабым шансом получим deadlock, потому что завершение потока приводит к вызову DllMain, которая блокирована главным потоком. Потоки должны закрыться до того, как DLL начнёт процесс выгрузки. |
| Автор: xkor 26.7.2010, 00:15 | ||||
блин точно, как то не подумал об этом...
и как тогда потоки должны узнавать о том что процессу вот вот настанет конец? |
| Автор: CodeMonkey 26.7.2010, 11:16 | ||
Очевидно, что протокол DLL должен предусматривать функцию Done (и Init). Часто народ думает: во, у нас же есть DllMain! Давайте сюда поместим инициализацию и очистку ресурсов (в нашем случае: остановку потоков). Но они не осознают, что http://www.transl-gunsmoker.ru/2009/01/dllmain.html. К примеру, пакеты Delphi так и устроены: несмотря на то, что это просто DLL, их инициализация и финализация выброшены в отдельные функции, а не выполняется в рамках DllMain. |
| Автор: Dota 27.7.2010, 19:43 |
| Я пока придумал решение - использовать критические секции в DLLMain. Поток в начале работы входит в критическую секцию. И DLLMain тоже входит. Пока поток не покинет критическую секцию DLLMain будет ждать... |
| Автор: CodeMonkey 28.7.2010, 11:34 | ||
Поздравляю, ваши шансы на deadlock только что удвоились. Если раньше у вас была только блокировка загрузчика, то теперь у вас есть ещё и критическая секция. |
| Автор: Dota 28.7.2010, 12:50 |
| Но ведь критическая секция работает, если верить Рихтеру на пользовательском уровне, оперируя атомарными операциями... Есть ли способ доработать потоку правильными методами? |
| Автор: CodeMonkey 28.7.2010, 13:43 | ||
А причём тут это? Что, по-вашему произойдёт, если один поток войдёт в критическую секцию (или в любой другой объект синхронизации) и будет ждать там другой поток, которому тоже нужно туда войти? Deadlock и получится. Вы, кажется, не поняли, о чём идёт речь. Попробуйте вдумчиво прочитать того же Рихтера, где он говорит про DllMain, или http://www.transl-gunsmoker.ru/2009/01/dllmain.html. |
| Автор: Dota 28.7.2010, 19:49 |
| Никак не могу прикинуть, где деадлок может случиться. Имеем 2 и более теоретически возможно возникающих потока в DLL. Запускаются потоки. Входим в критическую секцию. Внезапно завершается приложение, вызывается DLLMain с параметром DLL_PROCESS_DETACH. Входим в эту же критическую секцию. Ждем пока нам не отдадут управление над критической секцией. Завершаем DLLMain _не выходя из критической секции_, тоесть все потоки которые не начали работу, ожидая своей очереди, автоматически умрут с приложением. |
| Автор: Dota 28.7.2010, 21:00 |
| Попробывал использовать критическую секцию в DLLMain - фиг там, не пашет, сразу пропускает. Хотя сколько коду видел и сколько валяется на теренах интернета, где пользуются критическими секциями в DLLMain ничего не подозревая. Даже в официальных примерах MSDN, если память не изменяет! |
| Автор: bems 28.7.2010, 23:43 | ||
|
| Автор: Dota 29.7.2010, 10:39 |
| Вообщем ситуация такая. ExitProcess используемый всеми программами для корректного завершения убивает все остальные потоки, кроме того, с которого вызван ExitProcess еще до того, как вызывается DLLMain PROCESS_DETACH Единственное решение, еще написанное Рихтером - секас с перехватом ExitProcess. |
| Автор: Dota 29.7.2010, 11:13 |
| Решение найдено. Использование критической секции совместно с потоком в DLL_THREAD_DETACH. Пока поток не завершится, DLL_THREAD_DETACH будет ждать его завершения, вот и все, никакие ресурсы на стадии остановки потоков ясное дело не освобождаются, потому можно смело там юзать критические секции. Деадлок при грамотном программировании тоже малореален, если вообще реален. |
| Автор: Dota 29.7.2010, 14:11 |
| Млин. Это не выход, приложение может подвиснуть на время, при убиении какого то своего потока, пока не выполнится код в моем потоке. Я в шоке. Перерыл весь интернет и так и не нашел ответа, как дать возможность потоку доработать до конца... |