|
|
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Привет. Кто работал с потоками, подскажите, если в курсе. Вот есть у меня процесс, EXE. Он использует DLL. Та, в свою очередь, создает поток в этом процессе. Всю поддержку этого потока хотелось бы сконцентрировать в DLL, чтоб EXE-шник ни о чем таком не заботился. Когда завершается главный поток, который в EXE-шнике, то и процесс тоже завершается. И это приводит к автоматическому закрытию всех порожденных потоков. И вот тут заковыка. Этому потоку хотелось бы получить какое-то извещение, что сейчас все, процесс терминируется. И причем без явных вызовов из EXE. Не шлют ли потоку чего-то автоматом? Или там, при создании потока куда-нибудь тот или иной колбак отдать, или еще как. А то обрывают поток ничего не спросимши. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2005, 14:44 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Завершайте поток, когда DllMain вызывается с DLL_PROCESS_DETACH параметром. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2005, 15:03 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Да, спасибо saint. Вот пока я только и цепляюсь за этот POCESS_DETACH. Но проблема в том, что у меня иногда к моменту вызова DllMain с POCESS_DETACH потоки уже завершены. То есть бывает, что они еще живы, а бывает, что их уже нету. Можно вобщем то "доделать за поток", то, что он должен был бы сам сделать при штатном завершении, но тогда получается немного жутковатый код. А вообще мне как-то очень странно, неужели никак нельзя сказать - что хочу мол, чтоб потоку перед его закрытием дали шанс все закрыть. Ведь это же наверное почти всегда нужно... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2005, 17:15 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
С этими патоками ваще нипаймеш. То ани живы, то ани уже завиршины. То есть, то нет. Так фсегда с ними. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2005, 20:45 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Не ну реально же бестолковость какая-то, если поток никто не известит, что ему сейчас капец настанет, а, народ? Представьте например что окна бы закрывались без WM_CLOSE или хоть какого-нибудь WM_NCDESTROY. Что-то я никак в толк не возьму, ну что, совсем чтоли никакого нет подобного извещения, заделанного в систему? Самому всегда делать дополнительную функцию и из EXE ее вызывать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2005, 15:57 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Можно создать в том потоке окно, и просто не отображать его(не вызывать ShowWindow() ). И тогда можно слать туда сообщения. В добавок, главный процесс будет ждать пока не обработаеться посланное сообщение, что даст потоку сделать все что ему нужно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2005, 17:52 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Eugene7Можно создать в том потоке окно, и просто не отображать его(не вызывать ShowWindow() ). И тогда можно слать туда сообщения. В добавок, главный процесс будет ждать пока не обработаеться посланное сообщение, что даст потоку сделать все что ему нужно. Я может не понял в чем фишка такого решения, или как. Мне бы хотелось, чтобы главный процесс вообще ничего не знал об этих потоках, и никуда не слал ничего. Ведь потоки непосредственно не создает, он вызывает функцию из DLL. И уже она, DLL, при своей работе, создает эти потоки. Если же снять это требование, то можно просто вызывать перед окончанием процесса еще одну функцаю из той же "всем_пока_жду_завершения", или как то в таком духе. Но мне-то хотелось, чтобы экзешних никаких таких завершений не делал (ибо не его забота). Но, похоже, придется ему все же беспокоиться, т.к. не видно иных способов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2005, 18:09 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Можно создать в главном потоке именованное событие, которое будет устанавливаться при его завершении. Дочерние потоки получают его хандл по имени и периодически ожидают. Код: plaintext Код: plaintext ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2005, 09:20 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Вас понял. Действительно, так хорошо. Хенделы дочерних потоков известны внутри DLL, и второй из способов был бы вполне приемлем. Вот если бы только весь этот код, связанный с действиями в главном потоке, можно было сконцентрировать в DLL, и причем так, чтобы EXE не знало об этом ничего, то было бы супер. Допустим я бы сделал в DLL функцию ShutDown(), где бы создавалось такое событие и его ожидание выполнялось. Теперь нужно сделать, чтобы функция эта выполнилась в главном потоке. Если бы только к моменту вызова DllMain с параметром DLL_PROCESS_DETACH потоки еще не были прерваны, то как раз сюда можно было бы вставить вызов ShutDown(). Но, вот ведь, они уже прерваны, так что пирдется мне вызывать ShutDown() из екзешника перед return 0. То есть код в exe вместо Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. выглядит как Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Вот то, что по любому необходим этот последней вызов, это и смущает. Ну, ладно, так уж оно видать нужно :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2005, 11:11 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Бармолей....Вот то, что по любому необходим этот последней вызов, это и смущает. Ну, ладно, так уж оно видать нужно :) 1) если говорить о потоках, то нужно помнить, что необходимо обеспечить две СИНХРОННЫЕ фазы. Старт и стоп асинхронного потока. Иначе нахрен Вам вообще порождать поток, если Вам всё равно его состояние. Картина станет яснее, если Ваша многопоточная модель будет подверженна "ударной нагрузке". Вот тогда все Ваши предположения об очерёдности событий полетят к чёрту...и только синхронные точки Вам помогут... 2) Есди Вам не нравиться вызов перед ретурном, никто Вам не мешает сделать АВТОМАТИЧЕСКИ удаляемый обьект и вложить его в фигурные скобочки (более элегантно - завуалировать трай кэтчем и иже)...Тогда деструктор отработает автоматом и позовёт СИНХРОННУЮ фазу останова потока... 3) Синхронность мона обеспечивать в принцепе любыми обьектами синхронизации ЯДРА win32. 4) асинхронные потоки лучше оформить классом. примеры - см. в МСДНе и в си бимоле (шарпе)... 5) после создании модели асинхронности Вашего приложения, рекомендую задуматься над приоритетами потоков, над потоками прохождения данных и т.д.. Однако изменять приоритеты потоков более чем на две позиции не рекомендую... с уважением (круглый) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2005, 13:51 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Колобок, допустим я буду наружу из своей длл не только функции давать, но и врапер в виде класса. Не хочешь помнить о завершении - используй врапер. Вроде мощняк. Но если писатель экзешника не в WinMain этот врапер заюзает, то тогда будет неахти. Значит нужно ему 2 класса - один использовать в WinMain, и там в деструкторе все завершаться будет, а другой - во всех остальных функциях. Так следует ли настолько его глаз на елку натягивать :) , и не проще ли все таки так и сказать - вызывай, дорогой товарищ, перед ретурном из WinMain функцию завершения, а то хуже будет. А то что состояние того потока не особо важно - так это такая задача. И синхронность вовсе не нужна, там просто окно вылезает немодальное. Хошь - жмешь на него. А не нажал так и ладно, и все асинхронно. С уважением (жуткий) :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2005, 15:55 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Бармолей, оказалось что мы коллеги по несчастью. У меня тоже зацепка на PROCESS_DETACH. Дальше придумал енумерацию процессов, но дальше как... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 13:40 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Боря, сострадаю :) У меня все эти потоки, ну точнее объектики у которых хенделы, собраны в разные списки, так что нет (вроде бы) необходимости в енумерации. Но бяка в том, что, вот если например поставить брейкпоинт в DllMain и посмотреть количество потоков в Task Manager' е, то оно, если можно так выразиться, "мало предсказуемо". То есть например, стоишь в DllMain (в главном потоке), потоков N, потом выполнишь одну инструкцию, глядь - а потоков уже и нету. В связи с этим можно предположить, что сбрасывание потоков начинается где-то до того, как вызвано DllMain(... PROCESS_DETACH ...). А вот как и где оно идет - этого я не знаю. Поскольку полагаться на такое ненадежное дело не хочется, я сделал в DLL специальную функцию CloseAll(), которая, грубо говоря, обеспечивает посылку каждому из потоков PostThreadMessage(...WM_QUIT...) и ожидание окончания. Если я правильно понял Колобка, это выходит вроде как необходимая для правильной работы вторая синхронная фаза. Но, с некоторым недоумением думаю теперь, откуда ж эту функцию вызывать-то :D. Ну если мою DLL использует экзешник напрямую, то ясно - перед финальным ретурном. А если ее использует не экзешник, а другая DLL? Вставлять в принадлежащую этой другой библиотеке функцию DllMain нет надежи, т.к. неизвестно соотношение моментов обрыва потоков и отгрузки DLL при неявной линковке. Что же (о ужас!) неужто нужно будет специально линковать эту DLL к главному exe только с одной целью чтобы вызвать перед ретурном функцию типа моей CloseAll() ? Это совсем уж странно... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 15:11 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Borya7...У меня тоже зацепка на PROCESS_DETACH.... дело в том, что процесс деаттач не всегда играет (особенно когда не ручками зовут дэлеле). более того, он вызываеться когда уже памяти сказали - свободна как фанера. и Ваши манипулирования на данной точке будут вызывать много веселья.... [quot Бармолей]...допустим я буду наружу из своей длл не только функции давать, но и врапер в виде класса. Не хочешь помнить о завершении - используй врапер. Вроде мощняк. Но если писатель экзешника не в WinMain этот врапер заюзает, то тогда будет неахти. Значит нужно ему 2 класса - один использовать в WinMain, и там в деструкторе все завершаться будет, а другой - во всех остальных функциях. .......и не проще ли все таки так и сказать - вызывай, дорогой товарищ, перед ретурном из WinMain функцию завершения, а то хуже будет. А то что состояние того потока не особо важно - так это такая задача. И синхронность вовсе не нужна, там просто окно вылезает немодальное. Хошь - жмешь на него. А не нажал так и ладно, и все асинхронно.[/quot Бармолей] что будет смотреть ножками наружу - пофигу. хоть регистры. рояли не играет. по поводу два врэпера - мыслю не понял. что то дюже намудренно. рекомендую глянуть Джэфри Элджера - увидите как с помощью одного зайца убить многих волков :) По поводу окна - наверное имеет глубокий смысл жать на то, что не имеет реакции:) хозяин барин... А по поводу мессаг - дескать отгужаюсь, дык там кнопок как то и не нуна... :) с уважением (круглый) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 15:19 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Бармолей.......Что же (о ужас!) неужто нужно будет специально линковать эту DLL к главному exe только с одной целью чтобы вызвать перед ретурном функцию типа моей CloseAll() ? Это совсем уж странно... иногда стоит правильно задать вопрос себе...предлагаю следующий... 1) действительно я тот первый пионэр, который идёт впереди планеты всей и столкнулся с ляпом архитектуры(языка, логики, глюком ОС - выбираешь что хочеться)? советую глянуть на COM. Там решаються похожие задачи. Вам никто не мешает подсчитывать кол-во ссылок и аккуратно отгружать на любой понравившейся Вам фазе работы. вот тут есть в электронном виде Джэфри Элджер - похоже он апрошла мимо Вас. На мой взгляд стоит взглянуть... хрюк (круглый) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 15:25 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Колобок благодарю зассылку занес в фаворитки. Читать-то немного лениво, но может и придется, думал может кто уже читал это до меня. Конечно я не пионер, оттого и спрашиваю, что думал будто дело это часто встречающееся и давно известное. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 18:19 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
А причем тут вообще COM и подсчет ссылок? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 18:23 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
kolobok0 Бармолей.......Что же (о ужас!) неужто нужно будет специально линковать эту DLL к главному exe только с одной целью чтобы вызвать перед ретурном функцию типа моей CloseAll() ? Это совсем уж странно... иногда стоит правильно задать вопрос себе...предлагаю следующий... 1) действительно я тот первый пионэр, который идёт впереди планеты всей и столкнулся с ляпом архитектуры(языка, логики, глюком ОС - выбираешь что хочеться)? советую глянуть на COM. Там решаються похожие задачи. Вам никто не мешает подсчитывать кол-во ссылок и аккуратно отгружать на любой понравившейся Вам фазе работы. вот тут есть в электронном виде Джэфри Элджер - похоже он апрошла мимо Вас. На мой взгляд стоит взглянуть... хрюк (круглый) Пишет "У вас нет прав для просмотра этой страницы". Может хрюкнешь еще что-нибудь(другую ссылку)? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 18:35 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
А почему собственно говоря, вы так боитесь вызывать из главного потока DLL_Shutdown()? На мой взгляд, такой подход очень даже хорош. При старте программы делаем DLL_Init() на выходе DLL_Shutdown(). Если есть боязнь что программа завершиться по исключению, то можно использовать atexit() и там уже перечислять все DLL1_Shutdown(), DLL2_CloseAll() и так далее :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 19:33 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Дык я не боюсь, мне то што, но два момента 1) если мою Dll использует другая DLL , то где вызывать? 2) если экзешник и ту другую DLL будут писать другие люди, какова вероятность того, что их это сильно порадует? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 19:44 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
БармолейДык я не боюсь, мне то што, но два момента 1) если мою Dll использует другая DLL , то где вызывать? В собственных SecondaryDll_Init() и SecondaryDll_Shutdown() конечно, где же еще? :) Бармолей2) если экзешник и ту другую DLL будут писать другие люди, какова вероятность того, что их это сильно порадует? :) Нуууу... вот я тебе скажу как человек использующий прямо сейчас с десяток dll имеющих Dll_Init() и Dll_Shutdown() - оно меня не напрягает совершенно. Даже наоборот удобно. Я точно знаю когда эта внешняя библиотека стартует и завершается даже при статичной линковке. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2005, 20:01 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
ExitProcess Remarks ... - During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process. - Only one thread in a process can be in a DLL initialization or detach routine at a time. - If any process is in its DLL initialization or detach routine, ExitProcess does not return. Колобок, что скажешь? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 08:37 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
White OwlНуууу... вот я тебе скажу как человек использующий прямо сейчас с десяток dll имеющих Dll_Init() и Dll_Shutdown() - оно меня не напрягает совершенно. Даже наоборот удобно. Я точно знаю когда эта внешняя библиотека стартует и завершается даже при статичной линковке. Может быть в итоге и мне придется также делать, но пока уж очень ломает. А вот мысля пришла такая, как вроде можно сделать иначе. Ввести небольшой протокольчик для корректного завершения, и тогда потоки, желающие всегда завершаться штатно, должны будут его поддержать. Библиотеки, использующие мою, о корректном завершении заботиться не должны - все перекладываем на экзешник. Для этого замутить отдельную DLL. Она обязательно должна подключаться к экзешнику. Она собирает в своем DllMain все потоки, когда ее вызывают с ThreadAttach/Detach. Это чтоб потом мучительно не искать их. Но, самое главное не в этом, а в том, что в ней есть функцайка корректного завершения. Ее должен вызывать только экзешник и только в одном месте - перед финальным ретурном. В сей функцайке перебираем все потоки, не зная - откуда они и зачем. Тут хорошо бы послать каждой из них какую-нибудь опознавательную месагу, типа, "ты поддерживаешь или не поддерживаешь описываемый протокол?". Если поддерживает, то тут же постим ему WM_QUIT и WaitForSingleObject(hThread). И он штатно завершается. Но, небольшая проблемка с опознавательной месагой. У нас есть только PostThreadMessage, SendThreadMessage нету. Значит мы должны сделать PostThreadMessage и подождать ответа (ивента к примеру), но как долго ждать, если данный поток такой протокол не поддерживает и не ждет подобных никаких опознавательных сигналов. Однако, тут можно так. Слать опознавательную месагу не в момент завершения, а в момент подключения, для чего организовать спец-поток ожидания ответного ивента. Если к моменту завершения прикладной поток ответил этому спец-потоку ивентом, значит он "наш", иначе - его проблемы. Не делал ли так кто нибудь, а? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 11:52 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Бармолей White OwlНуууу... вот я тебе скажу как человек использующий прямо сейчас с десяток dll имеющих Dll_Init() и Dll_Shutdown() - оно меня не напрягает совершенно. Даже наоборот удобно. Я точно знаю когда эта внешняя библиотека стартует и завершается даже при статичной линковке. Может быть в итоге и мне придется также делать, но пока уж очень ломает. А вот мысля пришла такая, как вроде можно сделать иначе. Ввести небольшой протокольчик для корректного завершения, и тогда потоки, желающие всегда завершаться штатно, должны будут его поддержать. Библиотеки, использующие мою, о корректном завершении заботиться не должны - все перекладываем на экзешник. Для этого замутить отдельную DLL. Она обязательно должна подключаться к экзешнику. Она собирает в своем DllMain все потоки, когда ее вызывают с ThreadAttach/Detach. Это чтоб потом мучительно не искать их. Но, самое главное не в этом, а в том, что в ней есть функцайка корректного завершения. Ее должен вызывать только экзешник и только в одном месте - перед финальным ретурном. В сей функцайке перебираем все потоки, не зная - откуда они и зачем. Тут хорошо бы послать каждой из них какую-нибудь опознавательную месагу, типа, "ты поддерживаешь или не поддерживаешь описываемый протокол?". Если поддерживает, то тут же постим ему WM_QUIT и WaitForSingleObject(hThread). И он штатно завершается. Но, небольшая проблемка с опознавательной месагой. У нас есть только PostThreadMessage, SendThreadMessage нету. Значит мы должны сделать PostThreadMessage и подождать ответа (ивента к примеру), но как долго ждать, если данный поток такой протокол не поддерживает и не ждет подобных никаких опознавательных сигналов. Однако, тут можно так. Слать опознавательную месагу не в момент завершения, а в момент подключения, для чего организовать спец-поток ожидания ответного ивента. Если к моменту завершения прикладной поток ответил этому спец-потоку ивентом, значит он "наш", иначе - его проблемы. Не делал ли так кто нибудь, а? При таком подходе экономичнее будет пару макросов написать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 12:12 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=33455872&tid=2032159]: |
0ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
157ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
| others: | 244ms |
| total: | 506ms |

| 0 / 0 |
