シングル スレッド アパートメントを必要とする COM オブジェクトを作成するスレッドがあります。
もともと、このスレッドのメイン関数は、WaitForMultipleObjects ループに入れていました。COM メッセージ ポンプが本来の役割を果たせなくなるため、これは明らかに問題です。
解決策としてこれを MsgWaitForMultipleObjects に置き換えましたが、現在問題が発生しています。
このコードは、処理を続行して MsgWaitForMultipleObjects を再度呼び出すことで、WAIT_FAILED の戻り値を処理します。MsgWaitForMultipleObjects を呼び出すと、WAIT_FAILED が数回返されることがあります (私が見た中で最も多かったのは 9 回です) が、突然問題なく動作します。
このコードは、関数が正当な理由で WAIT_FAILED を返した場合に無限ループに陥る可能性があるように記述されています。これを修正する必要があることはわかっていますが、MsgWaitForMultipleObjects 呼び出しが最終的に成功するため、現時点では「回避策」と考えています。
このコードは、Windows 7、Vista、および XP (すべて 32 ビット、Windows 7 32 ビットおよび 64 ビット) でテストされています。
なぜこれが起こっているのか誰にも分かりますか?
関連するコード:
bool run = true;
while (run)
{
DWORD ret = MsgWaitForMultipleObjects(2, events, FALSE, INFINITE,
QS_ALLINPUT);
switch (ret)
{
case WAIT_OBJECT_0:
{
ResetEvent(events[0]);
ProcessWorkQueue();
break;
}
case WAIT_OBJECT_0 + 1:
{
run = false;
break;
}
case WAIT_OBJECT_0 + 2:
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
DispatchMessage(&msg);
break;
}
case WAIT_FAILED:
{
Logger::Output(L"Wait failed in Notify::Run(), error is "
+ boost::lexical_cast<std::wstring>(GetLastError()));
}
}
}
出力例は次のとおりです。
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
// At this point, the wait succeeds
WAIT_FAILED の戻り値は、メッセージによって待機が中断された後にのみ発生していると思います。