|
|
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#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 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
_БалтикаПри таком подходе экономичнее будет пару макросов написать Каких? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 12:21 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Бармолей _БалтикаПри таком подходе экономичнее будет пару макросов написать Каких? На самом деле их три должно быть 1. С определениями 2-х функций: а) функции потока регистрации потоков, поддерживающих протокол (кстати, не проще-ли сделать, чтобы сами потоки посылали сообщения, например установкой некоторого события) и б) функции завершения. 2. Запуска потока (а) 3. Вызова функции (б) далее Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 12:46 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
В этот же хедер можно и протокол для dll-ов забить, написав свою функцию запуска потоков. Ну, примерно так Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 13:22 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Можно и так, но: 1) Поток может завершиться штатно и до завершения процесса, и тогда наши пританцовки в конце процесса для него не нужны. Надо будет исключать его из списка - еще один макрос, но уже в каждой реализации потока. 2) Очень жесткое требование, чтобы в большой программе всякое создание потоков проходило только через определенный макрос. А если мы будем это ловить в уже предоставленной системой функции DllMain, такое требование снимается. Кроме того, с использованием DLL экзешник лаконичнее Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. От писателя экзешника требуется только не забыть включить одну строчку [***]. Других ошибок ему не дадут сделать компилятор и линкер. С другой стороны, писатели потоков вообще не будут должны что-то делать. Но, когда они осознают, что могут много чего потерять при завершении процесса, и ужаснутся, им скажут - положись на ThreadMngr, и ты в 2 шагах от успеха :): 1) Поддержи у себя обработку 1 идентификационного сообщения. Дело не хитрое. Пришлют тебе ивент, а ты его и выстави. Вот тут можно и макрос предусмотреть. 2) А еще поддержи WM_QUIT. Завершайся по нему штатно. Это уж совсем просто будет, обычным образом написанный цикл обработки сообщений всегда завершится по WM_QUIT. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 15:54 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
1) Описатели потоков в менеджере можно заносить в массив hThreadArray и ожидать их WaitForMultipleObject, и, дождавшись, исключать из hThreadArray 2) рекомендуют же разработчики vcишной библиотеки использовать вместо апишной CreateThreade - _beginthreadex из-за заморочек в других библиотеках. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 16:11 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
это да ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 16:44 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
БармолейБиблиотеки, использующие мою, о корректном завершении заботиться не должны - все перекладываем на экзешник. Для этого замутить отдельную DLL. .... Вот на такой подход я точно буду ругаться :) Одно дело знать что используемая библиотека требует явного старта и финиша (те самые DLL_Init() и DLL_Shutdown()) и совсем другое дело подключать какую-то еще dll причем надо будет следить чтобы она стартовала ДО рабочей dll и финишировала ПОСЛЕ нее. Получаем в итоге ту же самую проблему от которой пытались уйти только в еще более неудобном для решения виде. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.12.2005, 17:47 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Я конечно не супергуру и может что-то проскользнуло мимо меня, но какого извините меня не воспользоваться: DllMain: DLL_THREAD_ATTACH DLL_THREAD_DETACH Атачте библиотеку статически и следите за потоками на здоровье. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.12.2005, 14:56 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
saintЯ конечно не супергуру и может что-то проскользнуло мимо меня, но какого извините меня не воспользоваться: Потому что DllMain вызывается системой ПОСЛЕ того как система сама вычистила все принадлежащие процессу треды. Плюс к этому DLL_PROCESS_DETACH может срабатывать в другом треде чем тот в котором работал DLL_PROCESS_ATTACH. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.12.2005, 17:55 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Привет, всех с праздниками! :) Видимо собака была зарыта в том, что без стакана с этими трэдами не разберешься, а вот теперя вроде стало яснее :). Есть наверное разные варианты, но можно вот что сделать. Почти то, что предложил saint с использованием DllMain, только которое под нашим собственным контролем (т.к. увы DllMain вызывается когда уже потоки прерваны, и причем DLL_THREAD_DETACH вообще не вызывается если завершение нештатное). И одновременно это почти то, что говорил White Owl, но только не придется выстраивать DLL в непростые последовательности зависящих друг от друга. Вобщем, делается DLL (у меня она ThreadMngr), из которой торчит наружу такой API Код: plaintext 1. 2. Те потоки в разных DLL нашего большого проекта, которые хотят добиться того, чтобы непременно завершаться штатно, должны подлинковать эту специализированную DLL-синхронизатор. Когда они начинают свою работу, они регистрируются с помощью ThreadMngr_RegisterThread(..., TRUE). Тут заодно передаем dwThreadId, который иначе, по одному только hThread из другого потока достать затруднительно. При штатном завершении поток вызывает ThreadMngr_RegisterThread(..., FALSE). Или можно на две отдельных функции разбить, не важно. Ну а экзешник таки перед финальным ретурном вызывает ThreadMngr_WaitThreads(). И в нем что-то типа Код: plaintext 1. 2. White Owl Бармолей Библиотеки, использующие мою, о корректном завершении заботиться не должны - все перекладываем на экзешник. Для этого замутить отдельную DLL. Вот на такой подход я точно буду ругаться :) Одно дело знать что используемая библиотека требует явного старта и финиша (те самые DLL_Init() и DLL_Shutdown()) и совсем другое дело подключать какую-то еще dll причем надо будет следить чтобы она стартовала ДО рабочей dll и финишировала ПОСЛЕ нее. Получаем в итоге ту же самую проблему от которой пытались уйти только в еще более неудобном для решения виде. Может я выразился в прошлый раз не так. В итоге получается, что о всех этих делах заботятся 2 стороны: 1) сам тот поток, который не хочет быть прерван "на полуслове" 2) экзешник, который "всему голова" :) А разные "третьи" возможные участники, ну то есть еще другие DLL, которые используют ту, которая генерит потоки, вот они уже не заботятся о вопросах корректного завершения тех потоков. Вроде так нормальненько :)). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2006, 16:03 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
БармолейМожет я выразился в прошлый раз не так. В итоге получается, что о всех этих делах заботятся 2 стороны: .... Вроде так нормальненько :)). Да нет, все так выразился. Просто вот наличие "специализированной DLL-синхронизатора" мне и не нравится. Совсем. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2006, 18:00 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
White Owl БармолейМожет я выразился в прошлый раз не так. В итоге получается, что о всех этих делах заботятся 2 стороны: .... Вроде так нормальненько :)). Да нет, все так выразился. Просто вот наличие "специализированной DLL-синхронизатора" мне и не нравится. Совсем. А что плохого? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2006, 18:59 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Бармолей White OwlДа нет, все так выразился. Просто вот наличие "специализированной DLL-синхронизатора" мне и не нравится. Совсем. А что плохого? Ну я уже писал что плохого.... Но если хочешь повторю: 1) тебе прийдется из основной программы звать эти самые Код: plaintext 1. 3) ненормальное завершение основной программы приведет к ненормальному завершению этого "синхронизатора" и у тебя получается та же самая проблема которую ты пытался решить вводя "синхронизатор", только уже на двух dll :) 4) еще одна dll в дистрибутиве, при этом не выполняющая никакой полезной функции. Синхронизация может быть конечно полезной, но с точки зрения основной задачи она не нужна. Лично я предпочту звать из основной программы пару функций Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2006, 19:31 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
А, понял. У тебя, выходит дело, уже есть такая система правил в проекте: 1) У всех dll должен быть инит и шатдаун 2) Если в одной dll используешь другую длл, то должен ей форвардить эти вызовы 3) Делаешь что-то типа подсчета ссылок, или еще как, но так чтобы 2 раза не заинититься и не зашатдауниться При таком раскладе да, уже есть место, где "всяко завершать", ну и тогда само собой просится сунуть ожидание потоков тоже в ту же шатдаун. Тут наверное нужны еще некие базовые классики, чтобы не повторять код... Ну а так как у меня нет такой глобальной системы, а вводить ее на данном этапе по ряду причин довольно проблемно, то пока что более локальным решением может быть сервис в виде отдельной dll, узко направленный конкретно на решение задач с потоками, то есть "синхронизатор" этот. На exe при этом ложится только задача обеспечения финального вызова Код: plaintext 1. Код: plaintext 1. По-моему тут во многом дело вкуса и проектной ситуации - на какой манер делать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2006, 14:54 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
БармолейА, понял. У тебя, выходит дело, уже есть такая система правил в проекте: 1) У всех dll должен быть инит и шатдаун 2) Если в одной dll используешь другую длл, то должен ей форвардить эти вызовы 3) Делаешь что-то типа подсчета ссылок, или еще как, но так чтобы 2 раза не заинититься и не зашатдауниться Нет, не правильно :) 1) Процедуры MyDLL_Init()/MyDLL_Shutdown() есть только у некоторых dll. Которым есть что инитить и шатдаунить :) Соотвественно в документации на эти dll явно сказано о необходимости этой пары (или только одной из) функций. 2) Никуда я ничего не форваржу. Если DllA использует DllB, а я из основной программы не обращаюсь к DllB, то соответсвенно мне совершенно до лампочки как DllA работает с DllB. У меня в программе есть DllA_Init() и DllA_Shutdown(). Все. Что там происходит внутри DllA меня не волнует. 3) Ну и соотвественно никаких подсчетов ссылок и ни о каких двойных ссылках я не забочусь. Если Dll не должна инитится дважды и/или должна обслуживать несколько программ одновременно, то она (dll) сама об этом заботится. Например создает мутекс во время своего Dll_Init и разбирается надо ли его удалять при Dll_Shutodown. Из основной программы я ничего не делаю совсем. БармолейПо-моему тут во многом дело вкуса и проектной ситуации - на какой манер делать. Это конечно да.... Просто подход который я описываю работает уже много-много лет, в очень-очень многих freeware/shareware и разных других ~ware рантайм-библиотеках :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2006, 18:01 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
White Owl БармолейА, понял. У тебя, выходит дело, уже есть такая система правил в проекте: 1) У всех dll должен быть инит и шатдаун 2) Если в одной dll используешь другую длл, то должен ей форвардить эти вызовы 3) Делаешь что-то типа подсчета ссылок, или еще как, но так чтобы 2 раза не заинититься и не зашатдауниться Нет, не правильно :) 1) Процедуры MyDLL_Init()/MyDLL_Shutdown() есть только у некоторых dll. Которым есть что инитить и шатдаунить :) Соотвественно в документации на эти dll явно сказано о необходимости этой пары (или только одной из) функций. 2) Никуда я ничего не форваржу. Если DllA использует DllB, а я из основной программы не обращаюсь к DllB, то соответсвенно мне совершенно до лампочки как DllA работает с DllB. У меня в программе есть DllA_Init() и DllA_Shutdown(). Все. Что там происходит внутри DllA меня не волнует. 3) Ну и соотвественно никаких подсчетов ссылок и ни о каких двойных ссылках я не забочусь. Если Dll не должна инитится дважды и/или должна обслуживать несколько программ одновременно, то она (dll) сама об этом заботится. Например создает мутекс во время своего Dll_Init и разбирается надо ли его удалять при Dll_Shutodown. Из основной программы я ничего не делаю совсем. 1) Так у тя еще и документация есть??!! :)) Ну ты это, вообще счастливчик, если она настолько приближена к реализации и при этом еще и в актуальном состоянии поддерживается. 2) Когда ты говоришь, что не форвардишь это имеется ввиду что экзехе пофиг что дальше сделает DLLA? Ну это круто, но ведь реально то все-таки будут возникать ситуации форварда. Вот например, есть у тебя цепочка использования EXE -> DllA -> DllB -> ... -> DllY -> DllZ. И вдруг DllZ, возьми себе да и реализуй новый функционал, где появляются потоки. Так автор DllZ должен сообщить своему другу, пишущему DllY: "ты теперь зови мне инит и шатдаун!", а тот автору DllX и т.д. вплоть до писателя экзешника. И вот, дописывая эту шатдаун, они только и должны будут, что вызвать шатдаун того, кого они используют. Про это я и говорил, что это форвардинг (он остается таковым даже если вызывающий модуль не вдается в то что происходит). 3) Когда ты говоришь "я не забочусь о подсчете ссылок" ты, вероятно имеешь ввиду вызывающую сторону, например экзешник. Ну а вызываемая сторона если только ее шатдаун и инит не сводятся к соответствующим форвардам, никуда не денется от того, чтобы как то позаботиться о возможности повторных вызовов. Поэтому, то что ты не делаешь контроль повторных вызовов означает скорее всего, что его делают другие. White Owl БармолейПо-моему тут во многом дело вкуса и проектной ситуации - на какой манер делать. Это конечно да.... Просто подход который я описываю работает уже много-много лет, в очень-очень многих freeware/shareware и разных других ~ware рантайм-библиотеках :) Клево :) Да, очень часто, когда кто-нибудь делал что-нибудь много-много лет, то он уже обычно и дальше продолжает в том же стиле, особенно если это приводит к результату, и в этом нет ничего плохого, если все это вполне работает. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2006, 19:55 |
|
||
|
Завершение потока путем окончания процесса
|
|||
|---|---|---|---|
|
#18+
Бармолей1) Так у тя еще и документация есть??!! :)) Ну ты это, вообще счастливчик, если она настолько приближена к реализации и при этом еще и в актуальном состоянии поддерживается. Конечно есть :) Нафига мне возится с недокументированным чужим произведением? Либо документация, либо исходники, а лучше и то и другое. Бармолей2) Когда ты говоришь, что не форвардишь это имеется ввиду что экзехе пофиг что дальше сделает DLLA? Ну это круто, но ведь реально то все-таки будут возникать ситуации форварда. Вот например, есть у тебя цепочка использования EXE -> DllA -> DllB -> ... -> DllY -> DllZ. И вдруг DllZ, возьми себе да и реализуй новый функционал, где появляются потоки. Так автор DllZ должен сообщить своему другу, пишущему DllY: "ты теперь зови мне инит и шатдаун!", а тот автору DllX и т.д. вплоть до писателя экзешника. И вот, дописывая эту шатдаун, они только и должны будут, что вызвать шатдаун того, кого они используют. Про это я и говорил, что это форвардинг (он остается таковым даже если вызывающий модуль не вдается в то что происходит).эээ.... ну в общем то да, все верно. Все именно так и происходит. Но! Есть одно такое очень сильное "но". :) Если DllZ изменился настолько что для новой версии DllZ нужно переписать DllY, то DllZ переименовывается в DllZ2 и в документации на нее появляется дополнительный текст "как мигрировать с DllZ на DllZ2". DllZ еще некоторе время поддерживается на тему исправления багов в ней (автор DllZ поддерживает две разных ветки!). Потом DllZ остается лежать в виде последнего билда... А в каждом дистрибутиве DllY будет пометка, что мол для версии DllY 1.2.3 использовалась DllZ, а начиная с DllY 1.3.0 будет использоваться DllZ2. И частенько соответсвующие версии DllZ* лежат в очередном дистрибутиве DllY. Это конечно не обязательное требование, это скорее правило хорошего тона. Но его придерживаются 99% всех писателей библиотек :) Бармолей3) Когда ты говоришь "я не забочусь о подсчете ссылок" ты, вероятно имеешь ввиду вызывающую сторону, например экзешник. Ну а вызываемая сторона если только ее шатдаун и инит не сводятся к соответствующим форвардам, никуда не денется от того, чтобы как то позаботиться о возможности повторных вызовов. Поэтому, то что ты не делаешь контроль повторных вызовов означает скорее всего, что его делают другие.Все верно. В общем, я тебе очень советую заглянуть на sourceforge.net, пошарься там по разным проектам. Обязательно найдешь что-нибудь вкусное и понаблюдай за развитием заинтересовавших проектов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2006, 23:34 |
|
||
|
|

start [/forum/topic.php?all=1&fid=57&tid=2032159]: |
0ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
164ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
69ms |
get tp. blocked users: |
1ms |
| others: | 249ms |
| total: | 526ms |

| 0 / 0 |
