У меня есть поток, который, когда его функция выходит из цикла (выход запускается событием), выполняет некоторую очистку, а затем устанавливает другое событие, чтобы главный поток знал, что это сделано.
Однако при некоторых обстоятельствах SetEvent (), по-видимому, не возвращается после того, как он установил событие потока «Я закончил».
Этот поток является частью DLL, и проблема возникает после того, как DLL была загружена / присоединена, поток запущен, поток завершен, а DLL несколько раз отключалась / выгружалась без остановки приложения между ними. Число повторений этой последовательности до возникновения этой проблемы является переменным.
В случае, если вы скептически относитесь к тому, что я знаю, о чем я говорю, я определил, что происходит, заключив вызов SetEvent () в скобки с вызовами OutputDebugString (). Вывод до SetEvent () появляется. Затем ожидающий поток выдает вывод, который указывает, что событие установлено.
Тем не менее, второй вызов OutputDebugString () в выходящем потоке (один после ПОСЛЕ SetEvent ()) никогда не происходит, или, по крайней мере, его строка никогда не обнаруживается. Если это произойдет, приложение вылетает через несколько секунд.
(Обратите внимание, что вызовы OutputDebugString () были добавлены после того, как проблема начала возникать, поэтому она вряд ли будет зависать там, а не в SetEvent ().)
Я не совсем уверен, что вызывает сбой, но это происходит в том же потоке, в котором SetEvent () не возвращался немедленно (я отслеживал / выводил идентификаторы потоков). Я предполагаю, что вполне возможно, что SetEvent () наконец-то возвращается, после чего контекст, к которому он возвращается, утерян / недействителен, но что может вызвать такую задержку?
Оказывается, я был ослеплен, глядя на этот код так долго, и мне даже не пришло в голову проверить код возврата. Я посмотрел на него сегодня, поэтому я буду знать, что он возвращает (, если возвращается) в понедельник, и тогда я отредактирую этот вопрос с этой информацией.
Обновление: я изменил (основной) код, чтобы дождаться завершения потока, а не для установки события, и удалил вызов SetEvent () из подчиненного потока. Это изменило природу ошибки: теперь, вместо того, чтобы не вернуться из SetEvent (), он вообще не выходит из потока и все зависает.
Это указывает на то, что проблема не в SetEvent (), а в чем-то более глубоком. Пока понятия не имею, но хорошо не преследовать этот тупик.
Обновление (13 февраля 2009 г.):
Оказалось, что проблема была глубже, чем я думал, когда задавал этот вопрос. jdigital (и, возможно, другие) в значительной степени преуменьшил основную проблему: мы пытались выгрузить поток как часть процесса отключения DLL.
Это, как я не осознавал в то время, но с тех пор выяснил это благодаря исследованиям здесь и в другом месте (например, в блоге Рэймонда Чена), это очень плохая вещь.
Проблема заключалась в том, что из-за того, как он был закодирован и как он себя вел, не было очевидным, что это было основной проблемой - он был замаскирован под все виды других Плохих Поведений, через которые мне пришлось пройти.
Некоторые из предложений здесь помогли мне сделать это, поэтому я благодарен всем, кто внес свой вклад. Спасибо!