Вопрос

У меня есть нить A, которая создает другую ветку B, чем нить A ждет, используя WaitForsingleObject, чтобы подождать, пока не умрет поток B.

Проблема в том, что, несмотря на то, что поток B возвращается из поток "thread_func", поток A не сигнализирует!.

Я знаю, что, поскольку я добавил трассы (outputDebugString) к концу thread_func (основная функция потока B), и я вижу, что поток B завершает свое выполнение, но нить A никогда не выходит из WaitForsingleObject.

Теперь я также должен добавить, что этот код находится в объекте COM, и сценарий, описанный выше, происходит, когда я вызывает regsvr32.exe (он застрял!), Поэтому я считаю, что поток A исходит из Dllmain.

Есть идеи, почему нить A не сигнализирует?!?!

Это было полезно?

Решение

Вы можете столкнуться с проблемой с блокировкой погрузчика. Windows имеет внутреннюю критическую раздел, который заблокируется всякий раз, когда DLL загружается/выгружается или при запуске поток/остановки (dllmain всегда называется внутри этой блокировки). Если ваш ожидающий поток A имеет этот критический раздел заблокирован (т.е. вы ждете где -то от Dllmain), в то время как другой поток B пытается выключить и пытается получить этот критический раздел загрузчика, у вас есть тупик.

Чтобы увидеть, где происходит тупик, просто запустите свое приложение от отладчика VS IDE, и после того, как оно застряло, разбивает выполнение. Затем посмотрите на все запуск потоков и обратите внимание на стек каждого из них. Вы должны быть в состоянии следить за каждым стеком и посмотреть, чего ждет каждый поток.

Другие советы

Я думаю, что @DXM прав. Документация о том, что вы можете или не можете сделать внутри DllMain Редко и трудно найти, но суть в том, что вы, как правило, должны держать его до минимума - инициализировать внутренние переменные и тому подобное, но это все.

Другой момент, который я подчеркнул, это то, что вы обычно должны нет "Call" Regsvr32.exe - когда -либо.

REGSVR32 - это всего лишь обертка, которая загружает DLL в свое адресное пространство с LoadLibrary, Звонки GetProcAddress Чтобы получить адрес функции именованной DllRegisterServer, затем вызывает эту функцию. Это намного чище (и, в конечном счете, проще) выполнять работу самостоятельно, что -то вроде этого:

HMODULE mod = LoadLibrary(your_COM_file); 
register_DLL = GetProcAddress(mod, "DllRegisterServer"); 
if ( register_DLL == NULL) { 
        // must not really be a COM object... 
} 

if ( S_OK != register_DLL()) { 
        // registration failed. 
} 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top