Windows для профессионалов

       

Уведомление DLL_THREAD_DETACH


Лучший способ завершить поток — дождаться возврата из его стартовой функции, после чего система вызовет ExitThread и закроет поток. Эта функция лишь сообщает системе о том, что поток хочет завершиться, но система не уничтожает его немедленно. Сначала она просматривает все проекции DLL, находящиеся в данный момент в адресном пространстве процесса, и заставляет завершаемый поток вызвать DllMain в каждой из этих DLL со значением DLL_THREAD_DETACH Тсм самым она уведомляет DLL модули о необходимости очистки, связанной с данным потоком. Например, DLLверсия библиотеки С/С++ освобождает блок данных, используемый для управления многопоточными приложениями.

Заметьте, что DLL может не дать потоку завершиться. Например, такое возможно, когда функция DllMain, получив уведомление DLL_THREAD_DETACH, входит в бесконечный цикл. А операционная система закрывает поток только после того, как все DLL заканчивают обработку этого уведомления.

NOTE:
Если поток завершается из-за того, что другой поток вызвал для него TerminateThread, система не вызывает DllMain со значением DLL_THREAD_DETACH Следовательно, ни одна DLL, спроецированная на адресное пространство процесса, не получит шанса на выполнение очистки до завершения потока, что может привести к потере данных Поэтому TetminateThread, как и TerminateProcess, можно использовать лишь в самом крайнем случае!

Если при отключении DLL еще выполняются какие-то потоки, то для них DllMain не вызывается со значением DLL_THREAD_DETACH Вы можете проверить это при обработке DLL_PROCESS_DETACH и провести необходимую очистку.

Ввиду упомянутых выше правил не исключена такая ситуация: поток вызывает LoadIibrary для загрузки DLL, в результате чего система вызывает из этой библиотеки DllMain со значением DLL_PROCESS_ATTACH. (В этом случае уведомление DLL_ THREAD_ATTACH не посылается.) Затем поток, загрузивший DLL, завершается, что приводит к новому вызову DllMain — на этот раз со значением DLL_THREAD_DETACH Библиотека уведомляется о завершении потока, хотя она не получала DLL_ THREAD_ATTACH, уведомляющего о его подключении. Поэтому будьте крайне осторожны при выполнении любой очистки, связанной с конкретным потоком К счастью, большинство программ пишется так, что LoadLibrary и FreeLibrary вызываются одним потоком.



Содержание раздела