Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Почему поток обрывается? при закрытии главного окна? 
:(
    Опции темы
Dota
Дата 24.7.2010, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 12.7.2008

Репутация: нет
Всего: нет



Почему поток обрывается при закрытии главного окна и завершается приложение?
Блин, где не читаю, везде пишут, что процесс завершится только тогда, когда завершится последний поток. А тут получается что то принудительно его завершает.
Ситуация усложняется еще и тем, что потоки собираюсь создавать в DLL и программа, которая будет использовать DLL точно также может в любой момент обрываться и обрывается поток...


Код

function TestThread(Parameter: Pointer): Integer;
var
  I: Integer;
begin
  for I := 1 to 10 do
  begin
    Form1.Edit1.Text := IntToStr(I);
    Sleep(1000);
  end;

  EndThread(0);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  T: LongWord;
begin
  CloseHandle(BeginThread(nil, 0, TestThread, nil, 0, T));
end;


Это сообщение отредактировал(а) Dota - 24.7.2010, 21:10
PM MAIL   Вверх
CodeMonkey
Дата 24.7.2010, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



Потому что "end." в dpr файле - это вызов Halt(0).


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
xkor
Дата 24.7.2010, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 8.1.2007
Где: Питер

Репутация: нет
Всего: 4



CodeMonkey, и это надо сказать вполне логично учитывая что на "end." ещё и finalization у всех модулей вызывается
Dota, прими как данность что в обычном дельфи-приложении основной поток должен умирать последним
Цитата(Dota @  24.7.2010,  19:36 Найти цитируемый пост)
Ситуация усложняется еще и тем, что потоки собираюсь создавать в DLL и программа, которая будет использовать DLL точно также может в любой момент обрываться и обрывается поток...

При завершении программы вроде должна вызываться основная функция длл (DllProc вроде обзывается в дельфи и её ещё надо обозначить иначе стандартная заглушка только finalization модулей вызовет, хотя можно и через них) с параметром что длл выгружается, вот в этот момент можно послать всем своим потокам сигнал что надо срочно завершаться и дождаться их завершения
Хотя не уверен что эта функция вызывается если программа завершается по Halt
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Dota
Дата 25.7.2010, 21:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 12.7.2008

Репутация: нет
Всего: нет



Спасибо. Теперь ясно, что не кошерно все устроено в этом плане.
PM MAIL   Вверх
CodeMonkey
Дата 25.7.2010, 23:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



Цитата(Dota @  25.7.2010,  22:25 Найти цитируемый пост)
Теперь ясно, что не кошерно все устроено в этом плане. 

Пффф. Будьте осторожны: ваши желания могут исполнится. И тогда вам это не понравится. Подумайте сами почему. xkor уже дал подсказку.

Цитата(xkor @  24.7.2010,  23:45 Найти цитируемый пост)
вот в этот момент можно послать всем своим потокам сигнал что надо срочно завершаться и дождаться их завершения

И с неслабым шансом получим deadlock, потому что завершение потока приводит к вызову DllMain, которая блокирована главным потоком.

Потоки должны закрыться до того, как DLL начнёт процесс выгрузки.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
xkor
Дата 26.7.2010, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 8.1.2007
Где: Питер

Репутация: нет
Всего: 4



Цитата(CodeMonkey @  25.7.2010,  23:45 Найти цитируемый пост)
И с неслабым шансом получим deadlock, потому что завершение потока приводит к вызову DllMain, которая блокирована главным потоком.

блин точно, как то не подумал об этом...
Цитата(CodeMonkey @  25.7.2010,  23:45 Найти цитируемый пост)
Потоки должны закрыться до того, как DLL начнёт процесс выгрузки. 

и как тогда потоки должны узнавать о том что процессу вот вот настанет конец?
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
CodeMonkey
Дата 26.7.2010, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



Цитата(xkor @  26.7.2010,  01:15 Найти цитируемый пост)
и как тогда потоки должны узнавать о том что процессу вот вот настанет конец? 


Очевидно, что протокол DLL должен предусматривать функцию Done (и Init).

Часто народ думает: во, у нас же есть DllMain! Давайте сюда поместим инициализацию и очистку ресурсов (в нашем случае: остановку потоков). Но они не осознают, что DllMain - это особое место.

К примеру, пакеты Delphi так и устроены: несмотря на то, что это просто DLL, их инициализация и финализация выброшены в отдельные функции, а не выполняется в рамках DllMain.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Dota
Дата 27.7.2010, 19:43 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 12.7.2008

Репутация: нет
Всего: нет



Я пока придумал решение - использовать критические секции в DLLMain. Поток в начале работы входит в критическую секцию. И DLLMain тоже входит. Пока поток не покинет критическую секцию DLLMain будет ждать...
PM MAIL   Вверх
CodeMonkey
Дата 28.7.2010, 11:34 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



Цитата(Dota @  27.7.2010,  20:43 Найти цитируемый пост)
Поток в начале работы входит в критическую секцию. И DLLMain тоже входит. Пока поток не покинет критическую секцию DLLMain будет ждать... 


Поздравляю, ваши шансы на deadlock только что удвоились. Если раньше у вас была только блокировка загрузчика, то теперь у вас есть ещё и критическая секция.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Dota
Дата 28.7.2010, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 12.7.2008

Репутация: нет
Всего: нет



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

Есть ли способ доработать потоку правильными методами?
PM MAIL   Вверх
CodeMonkey
Дата 28.7.2010, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



Цитата(Dota @  28.7.2010,  13:50 Найти цитируемый пост)
Но ведь критическая секция работает, если верить Рихтеру на пользовательском уровне, оперируя атомарными операциями...


А причём тут это? Что, по-вашему произойдёт, если один поток войдёт в критическую секцию (или в любой другой объект синхронизации) и будет ждать там другой поток, которому тоже нужно туда войти? Deadlock и получится.

Вы, кажется, не поняли, о чём идёт речь. Попробуйте вдумчиво прочитать того же Рихтера, где он говорит про DllMain, или эту серию из четырёх постов.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Dota
Дата 28.7.2010, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 12.7.2008

Репутация: нет
Всего: нет



Никак не могу прикинуть, где деадлок может случиться.

Имеем 2 и более теоретически возможно возникающих потока в DLL.

Запускаются потоки. Входим в критическую секцию. Внезапно завершается приложение, вызывается DLLMain с параметром DLL_PROCESS_DETACH. Входим в эту же критическую секцию. Ждем пока нам не отдадут управление над критической секцией. Завершаем DLLMain _не выходя из критической секции_, тоесть все потоки которые не начали работу, ожидая своей очереди, автоматически умрут с приложением.
PM MAIL   Вверх
Dota
Дата 28.7.2010, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 12.7.2008

Репутация: нет
Всего: нет



Попробывал использовать критическую секцию в DLLMain - фиг там, не пашет, сразу пропускает.
Хотя сколько коду видел и сколько валяется на теренах интернета, где пользуются критическими секциями в DLLMain ничего не подозревая. Даже в официальных примерах MSDN, если память не изменяет!
PM MAIL   Вверх
bems
Дата 28.7.2010, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 21
Всего: 88



Цитата(Dota @  28.7.2010,  12:50 Найти цитируемый пост)
Но ведь критическая секция работает, если верить Рихтеру на пользовательском уровне, оперируя атомарными операциями...
Нет, она _может_ отработать не заходя в кернелмод, если сразу не занята, или освобождается, пока не вытекет счетчик. А потом задействуется объект ядра.



--------------------
Обижено школьников: 8
PM MAIL   Вверх
Dota
Дата 29.7.2010, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 12.7.2008

Репутация: нет
Всего: нет



Вообщем ситуация такая. ExitProcess используемый всеми программами для корректного завершения убивает все остальные потоки, кроме того, с которого вызван ExitProcess еще до того, как вызывается DLLMain PROCESS_DETACH  smile 

Единственное решение, еще написанное Рихтером - секас с перехватом ExitProcess.

Это сообщение отредактировал(а) Dota - 29.7.2010, 10:57
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0993 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.