Потоки в ДЛЛ, когда надо их прибивать?
От: Аноним  
Дата: 21.03.03 13:54
Оценка:
Среда MSVC++ c MFC
Вопрос такой, есть основное приложение, оно запускает дополнительные потоки (в терминах MSDN userinterface thread, потоки наследуются от CWinThread) соответственно в каждом потоке свое окно.
Если закрываем дочерние окна — все нормально.
Если закрываем основное окно, то доп потоки убиваются уже без моего участия (что сильно расстраивает) причем убиваются они как то жестко, потому что даже WM_QUIT они не получают.

Проблема решается, отслеживанием того, чего насоздавали и рассылкой в CWinApp::ExitInstance() всем потокам WM_QUIT.

Однако, если теперь функциональность, связанную с доп потоками, вынести в ДЛЛ, то отслеживать и убивать их из основного приложения, становится совсем не хорошо — т.е. просто такой вариант нельзя делать в силу ограничений накладываемых на задачу. Соответствено, потоки убиваются не правильно — я бы не сильно переживал на этот счет, не настолько я пунктуальный программист, но работа потоков подразумевает создание временного файла который надо убивать по завершению потока(на самом деле все несколько сложнее, однако, суть дела не меняется), и то что это не происходит сильно напрягает.

Попытка отлова всевозможных DLL_THREAD_DETACH,DLL_PROCESS_DEATTACH,... в DllMain успехом не увенчались(вполне вероятно, что я просто не то в них делал) , но
DLL_THREAD_DETACH — ни разу не пришло
DLL_PROCESS_DEATTACH — приходит стабильно, но к этому времени мои доп потоки настолько занасилованы системой, что смысл их убивать уже нет, они и так не живые.
_________

Вот здесь исходники тестового приложения(~8КБ) тока ногами не пинать, я на С++ с MFC пишу всего полгода


21.03.03 17:52: Перенесено из 'C/C++'
Re: Потоки в ДЛЛ, когда надо их прибивать?
От: KonstBez  
Дата: 21.03.03 14:01
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Среда MSVC++ c MFC

А>Вопрос такой, есть основное приложение, оно запускает дополнительные потоки (в терминах MSDN userinterface thread, потоки наследуются от CWinThread) соответственно в каждом потоке свое окно.
А>Если закрываем дочерние окна — все нормально.
А>Если закрываем основное окно, то доп потоки убиваются уже без моего участия (что сильно расстраивает) причем убиваются они как то жестко, потому что даже WM_QUIT они не получают.

А>Проблема решается, отслеживанием того, чего насоздавали и рассылкой в CWinApp::ExitInstance() всем потокам WM_QUIT.


А>Однако, если теперь функциональность, связанную с доп потоками, вынести в ДЛЛ, то отслеживать и убивать их из основного приложения, становится совсем не хорошо — т.е. просто такой вариант нельзя делать в силу ограничений накладываемых на задачу. Соответствено, потоки убиваются не правильно — я бы не сильно переживал на этот счет, не настолько я пунктуальный программист, но работа потоков подразумевает создание временного файла который надо убивать по завершению потока(на самом деле все несколько сложнее, однако, суть дела не меняется), и то что это не происходит сильно напрягает.


А>Попытка отлова всевозможных DLL_THREAD_DETACH,DLL_PROCESS_DEATTACH,... в DllMain успехом не увенчались(вполне вероятно, что я просто не то в них делал) , но

А>DLL_THREAD_DETACH — ни разу не пришло
А>DLL_PROCESS_DEATTACH — приходит стабильно, но к этому времени мои доп потоки настолько занасилованы системой, что смысл их убивать уже нет, они и так не живые.
А>_________

А>Вот здесь исходники тестового приложения(~8КБ) тока ногами не пинать, я на С++ с MFC пишу всего полгода


Вполне реальный выход — вставить в dll функцию (экспортируемую) типа CloseChildWindows с требованием клиенту вызывать ее перед завершением основного приложения. dll тоже модуль и имеет право на свой обработчик завершения.
Re[2]: Потоки в ДЛЛ, когда надо их прибивать?
От: Аноним  
Дата: 21.03.03 14:13
Оценка:
KB>Вполне реальный выход — вставить в dll функцию (экспортируемую) типа CloseChildWindows с требованием клиенту вызывать ее перед завершением основного приложения. dll тоже модуль и имеет право на свой обработчик завершения.

Низя так, первое что я предложил это при создании потока в ДЛЛ посылать сообщение основному процессу, при умирании потока своей смертью тоже, а в CGeneralWinApp::ExitInstance() — давить не до давленных.
Но основное приложение на предмет доп фнкциональности дадут по трогать только при строгом док-ве, что по другому никак.... вот и мучаюсь
Re[3]: Потоки в ДЛЛ, когда надо их прибивать?
От: KonstBez  
Дата: 21.03.03 16:15
Оценка:
Здравствуйте, Аноним, Вы писали:

KB>>Вполне реальный выход — вставить в dll функцию (экспортируемую) типа CloseChildWindows с требованием клиенту вызывать ее перед завершением основного приложения. dll тоже модуль и имеет право на свой обработчик завершения.


А>Низя так, первое что я предложил это при создании потока в ДЛЛ посылать сообщение основному процессу, при умирании потока своей смертью тоже, а в CGeneralWinApp::ExitInstance() — давить не до давленных.

А>Но основное приложение на предмет доп фнкциональности дадут по трогать только при строгом док-ве, что по другому никак.... вот и мучаюсь

А дочерним окнам не приходит чего-нибудь тривиального типа WM_CLOSE?
Re[4]: Потоки в ДЛЛ, когда надо их прибивать?
От: Аноним  
Дата: 21.03.03 18:27
Оценка:
KB>А дочерним окнам не приходит чего-нибудь тривиального типа WM_CLOSE?

вся неприятность положения заключается в том, что окна создаваемые доп потоками они по первоначалу на длительный период времени заняты — там список заполняется здоровый (для чего в отдельный поток и вынесены), соответственно они вообще сообщения не обрабатывают, но при этом закрытие основного окна гасит потоки по любому и сразу, вне зависимости от того заполняется этот список или уже заполнен. соответственно WM_CLOSE не приходит, я то хотел найти момент когда доп окна гасят и поставить там какой-нибудь event, чтобы выскочить из процедуры заполнения списка, и нормально закончится, а момент этот все-таки, наверное, можно поймать только в ExitInstance основного приложения, потом уже поздно пить баржоми, система сама разбирается с моими потоками ....
Просто надеялся, что ошибюсь и можно как то измудриться и реализовать все внутри ДЛЛ, наверное, не выйдет
Re[5]: Потоки в ДЛЛ, когда надо их прибивать?
От: Frostbitten Россия  
Дата: 21.03.03 20:22
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Просто надеялся, что ошибюсь и можно как то измудриться и реализовать все внутри ДЛЛ, наверное, не выйдет


Нет, ну измудриться как раз таки можно — покрупному.

Поставить во всех dll'ках WH_GETMESSAGE хук (::SetWindowsHookEx) для основнового треда (из dll'ки можно поставить и общесистемный, но так, конечно, лучше не поступать). И в обработчике отлавливать WM_QUIT, запощщеный в главный тред. Хук будет вызван в контексте главного треда — в каждом из них ждите завершения соответствующего (этому хуку) треда.

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

Но скажу мое мнение — измудрение это полнейшее. В случает множества хуков, может упасть производительность главного треда (ведь тысячи глаз будут следить за _каждым_ посылаемым ему сообщением), во втором это жестокое усложнение архитектуры dll'лок.

P.S.
Когда уже дописывал, вспомнил, что тут топик проплывал флеймовый о возможной засаде при обработке именно WM_QUIT (ведь его постят через PostQuitMessage, а не как все остальные через PostMessage), что-то там со внутренними флагами, которые устанавливает PostQuitMessage, но по-моему это не относиться к этому делу, но вам стоит с ним ознакомиться (в гораздо большей степени, чем это сделал я(:. Топик SendMessage vs. PostMessage
Автор: DrMom
Дата: 21.02.03
, в особенности пост тов. Valerio, оцененный в 13 балов.
Re[6]: Потоки в ДЛЛ, когда надо их прибивать?
От: Аноним  
Дата: 22.03.03 04:42
Оценка:
А>>Просто надеялся, что ошибюсь и можно как то измудриться и реализовать все внутри ДЛЛ, наверное, не выйдет

F>Нет, ну измудриться как раз таки можно — покрупному.


F>Поставить во всех dll'ках WH_GETMESSAGE хук (::SetWindowsHookEx) для основнового треда (из dll'ки можно поставить и общесистемный, но так, конечно, лучше не поступать). И в обработчике отлавливать WM_QUIT, запощщеный в главный тред. Хук будет вызван в контексте главного треда — в каждом из них ждите завершения соответствующего (этому хуку) треда.


Спасибо, по крайней мере хоть какое-то решение, надеюсь правда до такого дело не дойдет, и все таки уговоримся чуть подкорректировать основное приложение, добавив убиение дочерних тредов.

F>Но скажу мое мнение — измудрение это полнейшее. В случает множества хуков, может упасть производительность главного треда (ведь тысячи глаз будут следить за _каждым_ посылаемым ему сообщением), во втором это жестокое усложнение архитектуры dll'лок.


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

спасибо за ссылку — сейчас зачитаю
Re: Потоки в ДЛЛ, когда надо их прибивать?
От: bnk СССР http://unmanagedvisio.com/
Дата: 22.03.03 16:28
Оценка:
Здравствуйте, Аноним, Вы писали:

А> работа потоков подразумевает создание временного файла который надо убивать по завершению потока(на самом деле все несколько сложнее, однако, суть дела не меняется), и то что это не происходит сильно напрягает.


может просто завести в DLL статическую глобальную переменную(класс) и в ее деструкторе поубивать всех нафиг и позакрывать все файлы ? Че-то типа:

// где-то в DLL

FILE* files[N];
HANDLE threads[N];

struct CloseAllFiles
{
  ~CloseAllFiles()
  {
     for (i = 0; i < N; ++i)
       TerminateThread(thread[i]);

     for (i = 0; i < N; ++i)
       if (file[i])
         fclose(i);
     }
  }
} Terminator;
Re[2]: Потоки в ДЛЛ, когда надо их прибивать?
От: Аноним  
Дата: 22.03.03 16:33
Оценка:
bnk>может просто завести в DLL статическую глобальную переменную(класс) и в ее деструкторе поубивать всех нафиг и позакрывать все файлы ? Че-то типа:

убивать уже поздно ... просто замочить лишние файлы как Вы сами понимаете не основная проблема.... в конце концов их то можно мочить и в DllMain на DLL_PROCESS_DEATTACH, просто хотелось все сделать по правильному, чтобы раз я завел потоки я их и убив.
Re[5]: Потоки в ДЛЛ, когда надо их прибивать?
От: Игорь Вартанов Ниоткуда  
Дата: 24.03.03 10:38
Оценка:
Здравствуйте, Аноним, Вы писали:

KB>>А дочерним окнам не приходит чего-нибудь тривиального типа WM_CLOSE?


А>вся неприятность положения заключается в том, что окна создаваемые доп потоками они по первоначалу на длительный период времени заняты — там список заполняется здоровый (для чего в отдельный поток и вынесены), соответственно они вообще сообщения не обрабатывают,


Смотрим дизайн MFC — один поток (главный, UI) крутит message loop и создает все оконные объекты, рабочие потоки поставляют данные визуальным контролам, о чем докладывают механизмами синхронизации. Здесь нужно сделать то же самое.

А>но при этом закрытие основного окна гасит потоки по любому и сразу, вне зависимости от того заполняется этот список или уже заполнен. соответственно WM_CLOSE не приходит,


Хэндлы потоков, похоже, закрываются, из чего система делает справедливый вывод, что их (потоки) смело можно грохнуть, ибо воспользоваться данными из них уже не представляется возможным.

А>я то хотел найти момент когда доп окна гасят и поставить там какой-нибудь event,


Потоки должны тогда регулярно проверяться на предмет этого event'а (речь именно о событии, а не посылке оконного сообщения).

А> чтобы выскочить из процедуры заполнения списка, и нормально закончится, а момент этот все-таки, наверное, можно поймать только в ExitInstance основного приложения, потом уже поздно пить баржоми, система сама разбирается с моими потоками ....

А>Просто надеялся, что ошибюсь и можно как то измудриться и реализовать все внутри ДЛЛ, наверное, не выйдет

Ошибаешься. Можно. Внутри. Выйдет.
---
С уважением,
Игорь
Re[6]: Потоки в ДЛЛ, когда надо их прибивать?
От: Alglib Россия  
Дата: 24.03.03 13:52
Оценка:
Здравствуйте, Игорь Вартанов, Вы писали:

А>>Просто надеялся, что ошибюсь и можно как то измудриться и реализовать все внутри ДЛЛ, наверное, не выйдет


ИВ>Ошибаешься. Можно. Внутри. Выйдет.


я наверное очень тупой, но какэто сделать их вашего поста не понял, какое событие и где надо ожидать?
Re[7]: Потоки в ДЛЛ, когда надо их прибивать?
От: Игорь Вартанов Ниоткуда  
Дата: 25.03.03 11:42
Оценка:
Здравствуйте, Alglib, Вы писали:

A>но какэто сделать их вашего поста не понял, какое событие и где надо ожидать?


Главное окно создается, и при этом создается объект ядра "event" в несигнальном состоянии.


   HANDLE hStopEvent =
   CreateEvent( NULL  /*standard security attributes*/,
                TRUE  /*manual reset*/, 
                FALSE /*non-signalled initially*/, 
                NULL  /*nameless*/);



Далее всем порождаемым потокам передается его хэндл, на котором они (потоки) периодически должны делать WaitForSingleObject() с нулевым таймаутом. Если объект в несигнальном состоянии ("можно работать"), то она вернет WAIT_TIMEOUT, если же в потоке главного окна произошло "нечто" (SetEvent(hStopEvent)), в результате чего событие установлено в сигнальное состояние, то Wait-функция вернет WAIT_OBJECT_0, что значит "событие установлено, бросай все, щас будут убивать".

Если мирное завершение потоков занимает значительное время, тот необходимо наладить обратную связь — главное окно умрет лишь после того, как все потоки доложат о завершении (либо после защитного таймаута разумной продолжительности, если возможны зависы в потоках).

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

Если все кажется сложным, то рекомендую написать приложение-болванку, на которой обкатать основную схему взаимодействия окон, потоков и событий. После все будет казаться ясным и логичным.
---
С уважением,
Игорь
Re[8]: Потоки в ДЛЛ, когда надо их прибивать?
От: Alglib Россия  
Дата: 25.03.03 12:06
Оценка:
Основное условие задачи "нельзя менять основное приложение" если бы было можно, вопросов бы не было,

ИВ>Главное окно создается, и при этом создается объект ядра "event" в несигнальном состоянии.


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

ИВ>

ИВ>Далее всем порождаемым потокам передается его хэндл, на котором они (потоки) периодически должны делать WaitForSingleObject() с нулевым таймаутом. Если объект в несигнальном состоянии ("можно работать"), то она вернет WAIT_TIMEOUT, если же в потоке главного окна произошло "нечто" (SetEvent(hStopEvent)), в результате чего событие установлено в сигнальное состояние, то Wait-функция вернет WAIT_OBJECT_0, что значит "событие установлено, бросай все, щас будут убивать".


ИВ>Если мирное завершение потоков занимает значительное время, тот необходимо наладить обратную связь — главное окно умрет лишь после того, как все потоки доложат о завершении (либо после защитного таймаута разумной продолжительности, если возможны зависы в потоках).


ну не могу я главное приложение менять.
Re[9]: Потоки в ДЛЛ, когда надо их прибивать?
От: Игорь Вартанов Ниоткуда  
Дата: 26.03.03 18:28
Оценка:
Здравствуйте, Alglib, Вы писали:

A>ну не могу я главное приложение менять.


Ладно, не можешь — не надо. Но развести оконный и рабочий потоки для каждого окна ты можешь? Окно будет "живым" и сможет получить WM_CLOSE и посредством события (да-да, в этой ситуации у каждого окна будет два потока и событие для возможной остановки рабочего потока) стопить поток данных.

Кстати, это будет весомым аргументом для умников, не желающих менять основное приложение — "хотите — будет вам куча потоков и объектов ядра".
---
С уважением,
Игорь
Re[10]: Потоки в ДЛЛ, когда надо их прибивать?
От: Alglib Россия  
Дата: 27.03.03 09:30
Оценка:
Здравствуйте, Игорь Вартанов, Вы писали:
A>>ну не могу я главное приложение менять.

ИВ>Ладно, не можешь — не надо. Но развести оконный и рабочий потоки для каждого окна ты можешь? Окно будет "живым" и сможет получить WM_CLOSE и посредством события (да-да, в этой ситуации у каждого окна будет два потока и событие для возможной остановки рабочего потока) стопить поток данных.


что значит развести оконный и рабочий поток? и почему при этом WM_CLOSE будет приходить если сейчас в доп окна оно по закрытию основного не приходит? (вы меня извините за столь глупые вопросы — но не понимаю)

Вариант, когда доп окна работают в том же потоке, что основное, а вот данные в них запихиваются тн рабочим потоком, рассматривался — сложно получается, не так чтобы "ОЧЕНЬ СЛОЖНО" но не хотелось бы, через это по сути и начал пользовать юзверь интерфейс поток.

ИВ>Кстати, это будет весомым аргументом для умников, не желающих менять основное приложение — "хотите — будет вам куча потоков и объектов ядра".


нет тут вопрос не в том что они уперлись рогом, люди вполне вменяемы, просто менять основное приложение, на основании просто моего пожелания — глупо, у меня нет достаточной квалификации, надо весомое подтверждение которым в том числе явилось отсутствие предложений на двух конференциях
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.