powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Завершение потока путем окончания процесса
17 сообщений из 42, страница 2 из 2
Завершение потока путем окончания процесса
    #33461674
_Балтика
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Бармолей _БалтикаПри таком подходе экономичнее будет пару макросов написать
Каких?
На самом деле их три должно быть
1. С определениями 2-х функций:
а) функции потока регистрации потоков, поддерживающих протокол (кстати, не проще-ли сделать, чтобы сами потоки посылали сообщения, например установкой некоторого события) и
б) функции завершения.
2. Запуска потока (а)
3. Вызова функции (б)

далее
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
#include "хедер с макросами.h"
..............................
макрос  1 
..............................
_main()
{
    макрос  2 
..............................
..............................
    макрос  3 
    return  0 ;
}
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33461824
_Балтика
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В этот же хедер можно и протокол для dll-ов забить, написав свою функцию запуска потоков.

Ну, примерно так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
HANDLE MyCreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  SIZE_T dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID lpParameter,
  DWORD dwCreationFlags,
  LPDWORD lpThreadId
);
{
    HANDLE hThread = ::CreateThread(lpThreadAttributes, dwStackSize, StartAddress,  lpParameter, dwCreationFlags, lpThreadId);
    if (hThread)
    {
          HANDLE hEvent = GetEvent(...);
          if (hEvent)
          {
//   Пишем  hThread в какую-нибудь общую область памяти  
....................................................................................
              ::SetEvent(hEvent);
           }
     }
}
Естественно, нужно продумать защиту общей области в которую hThread пишется, чтобы два длла ее одновременно изменить не могли.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33462412
Бармолей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Можно и так, но:
1) Поток может завершиться штатно и до завершения процесса, и тогда наши пританцовки в конце процесса для него не нужны. Надо будет исключать его из списка - еще один макрос, но уже в каждой реализации потока.
2) Очень жесткое требование, чтобы в большой программе всякое создание потоков проходило только через определенный макрос. А если мы будем это ловить в уже предоставленной системой функции DllMain, такое требование снимается.

Кроме того, с использованием DLL экзешник лаконичнее

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
#include "..\ThreadMngr\ThreadMngr.h"

int main()
{
    .....
    ThreadMngr_WaitForAllThreads(); // [***]
    return  0 ;
}

От писателя экзешника требуется только не забыть включить одну строчку [***]. Других ошибок ему не дадут сделать компилятор и линкер.

С другой стороны, писатели потоков вообще не будут должны что-то делать. Но, когда они осознают, что могут много чего потерять при завершении процесса, и ужаснутся, им скажут - положись на ThreadMngr, и ты в 2 шагах от успеха :):
1) Поддержи у себя обработку 1 идентификационного сообщения. Дело не хитрое. Пришлют тебе ивент, а ты его и выстави. Вот тут можно и макрос предусмотреть.
2) А еще поддержи WM_QUIT. Завершайся по нему штатно. Это уж совсем просто будет, обычным образом написанный цикл обработки сообщений всегда завершится по WM_QUIT.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33462470
_Балтика
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
1) Описатели потоков в менеджере можно заносить в массив hThreadArray и ожидать их WaitForMultipleObject, и, дождавшись, исключать из hThreadArray
2) рекомендуют же разработчики vcишной библиотеки использовать вместо апишной CreateThreade - _beginthreadex из-за заморочек в других библиотеках.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33462593
Бармолей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
это да
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33462832
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
БармолейБиблиотеки, использующие мою, о корректном завершении заботиться не должны - все перекладываем на экзешник. Для этого замутить отдельную DLL.
....

Вот на такой подход я точно буду ругаться :)
Одно дело знать что используемая библиотека требует явного старта и финиша (те самые DLL_Init() и DLL_Shutdown()) и совсем другое дело подключать какую-то еще dll причем надо будет следить чтобы она стартовала ДО рабочей dll и финишировала ПОСЛЕ нее. Получаем в итоге ту же самую проблему от которой пытались уйти только в еще более неудобном для решения виде.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33464508
saint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я конечно не супергуру и может что-то проскользнуло мимо меня, но какого извините меня не воспользоваться:

DllMain:
DLL_THREAD_ATTACH
DLL_THREAD_DETACH

Атачте библиотеку статически и следите за потоками на здоровье.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33464969
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
saintЯ конечно не супергуру и может что-то проскользнуло мимо меня, но какого извините меня не воспользоваться:
Потому что DllMain вызывается системой ПОСЛЕ того как система сама вычистила все принадлежащие процессу треды. Плюс к этому DLL_PROCESS_DETACH может срабатывать в другом треде чем тот в котором работал DLL_PROCESS_ATTACH.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33474637
Бармолей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет, всех с праздниками! :)

Видимо собака была зарыта в том, что без стакана с этими трэдами не разберешься, а вот теперя вроде стало яснее :). Есть наверное разные варианты, но можно вот что сделать. Почти то, что предложил saint с использованием DllMain, только которое под нашим собственным контролем (т.к. увы DllMain вызывается когда уже потоки прерваны, и причем DLL_THREAD_DETACH вообще не вызывается если завершение нештатное). И одновременно это почти то, что говорил White Owl, но только не придется выстраивать DLL в непростые последовательности зависящих друг от друга.
Вобщем, делается DLL (у меня она ThreadMngr), из которой торчит наружу такой API

Код: plaintext
1.
2.
THREADMNGR_API void ThreadMngr_RegisterThread(HANDLE hThread, DWORD dwThreadId, BOOL bAttach);
THREADMNGR_API void ThreadMngr_WaitThreads();

Те потоки в разных DLL нашего большого проекта, которые хотят добиться того, чтобы непременно завершаться штатно, должны подлинковать эту специализированную DLL-синхронизатор. Когда они начинают свою работу, они регистрируются с помощью ThreadMngr_RegisterThread(..., TRUE). Тут заодно передаем dwThreadId, который иначе, по одному только hThread из другого потока достать затруднительно. При штатном завершении поток вызывает ThreadMngr_RegisterThread(..., FALSE). Или можно на две отдельных функции разбить, не важно.
Ну а экзешник таки перед финальным ретурном вызывает ThreadMngr_WaitThreads(). И в нем что-то типа

Код: plaintext
1.
2.
	::PostThreadMessage(dwThreadId, WM_QUIT,  0 , 0L);
	::WaitForSingleObject(hThread, INFINITE);

White Owl
Бармолей
Библиотеки, использующие мою, о корректном завершении заботиться не должны - все перекладываем на экзешник. Для этого замутить отдельную DLL.

Вот на такой подход я точно буду ругаться :)
Одно дело знать что используемая библиотека требует явного старта и финиша (те самые DLL_Init() и DLL_Shutdown()) и совсем другое дело подключать какую-то еще dll причем надо будет следить чтобы она стартовала ДО рабочей dll и финишировала ПОСЛЕ нее. Получаем в итоге ту же самую проблему от которой пытались уйти только в еще более неудобном для решения виде.

Может я выразился в прошлый раз не так. В итоге получается, что о всех этих делах заботятся 2 стороны:
1) сам тот поток, который не хочет быть прерван "на полуслове"
2) экзешник, который "всему голова" :)
А разные "третьи" возможные участники, ну то есть еще другие DLL, которые используют ту, которая генерит потоки, вот они уже не заботятся о вопросах корректного завершения тех потоков.

Вроде так нормальненько :)).
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33474942
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
БармолейМожет я выразился в прошлый раз не так. В итоге получается, что о всех этих делах заботятся 2 стороны:
....
Вроде так нормальненько :)).
Да нет, все так выразился. Просто вот наличие "специализированной DLL-синхронизатора" мне и не нравится. Совсем.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33475042
Бармолей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl БармолейМожет я выразился в прошлый раз не так. В итоге получается, что о всех этих делах заботятся 2 стороны:
....
Вроде так нормальненько :)).
Да нет, все так выразился. Просто вот наличие "специализированной DLL-синхронизатора" мне и не нравится. Совсем.
А что плохого?
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33475090
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бармолей White OwlДа нет, все так выразился. Просто вот наличие "специализированной DLL-синхронизатора" мне и не нравится. Совсем.
А что плохого?
Ну я уже писал что плохого.... Но если хочешь повторю:
1) тебе прийдется из основной программы звать эти самые
Код: plaintext
1.
THREADMNGR_API void ThreadMngr_RegisterThread(HANDLE hThread, DWORD dwThreadId, BOOL bAttach);
THREADMNGR_API void ThreadMngr_WaitThreads();
2) из рабочей dll надо будет регестрировать свои треды в этом "синхронизаторе".
3) ненормальное завершение основной программы приведет к ненормальному завершению этого "синхронизатора" и у тебя получается та же самая проблема которую ты пытался решить вводя "синхронизатор", только уже на двух dll :)
4) еще одна dll в дистрибутиве, при этом не выполняющая никакой полезной функции. Синхронизация может быть конечно полезной, но с точки зрения основной задачи она не нужна.

Лично я предпочту звать из основной программы пару функций
Код: plaintext
1.
void MyDll_Init(void);
void MyDll_Shutdown(void);
А уж они пусть разбираются со всеми внутренними тредами, со всеми файлами, буферами и тд и тп.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33476679
Бармолей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А, понял. У тебя, выходит дело, уже есть такая система правил в проекте:
1) У всех dll должен быть инит и шатдаун
2) Если в одной dll используешь другую длл, то должен ей форвардить эти вызовы
3) Делаешь что-то типа подсчета ссылок, или еще как, но так чтобы 2 раза не заинититься и не зашатдауниться

При таком раскладе да, уже есть место, где "всяко завершать", ну и тогда само собой просится сунуть ожидание потоков тоже в ту же шатдаун. Тут наверное нужны еще некие базовые классики, чтобы не повторять код... Ну а так как у меня нет такой глобальной системы, а вводить ее на данном этапе по ряду причин довольно проблемно, то пока что более локальным решением может быть сервис в виде отдельной dll, узко направленный конкретно на решение задач с потоками, то есть "синхронизатор" этот. На exe при этом ложится только задача обеспечения финального вызова
Код: plaintext
1.
    ThreadMngr_WaitThreads();
что не такая уж большая заморочка. А вот уже рабочие длл, порождающие свои потоки, при условии что они хотят завершаться штатно, должны будут приложить доп усилия в виде регистрирации.
Код: plaintext
1.
    ThreadMngr_RegisterThread(...);

По-моему тут во многом дело вкуса и проектной ситуации - на какой манер делать.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33477343
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. Из основной программы я ничего не делаю совсем.

БармолейПо-моему тут во многом дело вкуса и проектной ситуации - на какой манер делать.
Это конечно да.... Просто подход который я описываю работает уже много-много лет, в очень-очень многих freeware/shareware и разных других ~ware рантайм-библиотеках :)
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33477562
Бармолей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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 рантайм-библиотеках :)
Клево :) Да, очень часто, когда кто-нибудь делал что-нибудь много-много лет, то он уже обычно и дальше продолжает в том же стиле, особенно если это приводит к результату, и в этом нет ничего плохого, если все это вполне работает. :)
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33477715
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бармолей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, пошарься там по разным проектам. Обязательно найдешь что-нибудь вкусное и понаблюдай за развитием заинтересовавших проектов.
...
Рейтинг: 0 / 0
Завершение потока путем окончания процесса
    #33478121
Бармолей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо
...
Рейтинг: 0 / 0
17 сообщений из 42, страница 2 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Завершение потока путем окончания процесса
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]