MSGWAITFORMULTIPLEOBJECTSは、GetLasterRorの値なしでWait_Failedを返すことがあります
-
08-10-2019 - |
質問
単一のスレッドアパートメントを必要とするcomオブジェクトを作成するスレッドがあります。
もともと、このスレッドの主な関数は、それをwaitformultipleobjectsループに入れました。明らかにこれは問題です。なぜなら、それはCOMメッセージポンプが仕事をするのを防ぐからです。
これを解決策としてmsgwaitformultipleObjectsに置き換えましたが、今では問題に遭遇しています。MSGWAITFORMULTIPLEOBJECTSは時々(多くの場合)wait_failedを返しますが、エラーを設定しません。
コードは、継続して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の返品値は、メッセージによって壊れた後にのみ発生していると思います。
解決
それは起こってはならない、そして私は確かに正確に説明することはできない どうして します。ただし、いくつかのポインターがあります。
まず、あなたは電話していません TranslateMessage()
前 DispatchMessage()
メッセージポンプで。それは悪いジュジュです、そしてあなたは近くのどこにでも悪いジュジュを望んでいません MsgWaitForMultipleObjects()
.
また、明示的に電話をかけてみたいと思うかもしれません MsgWaitForMultipleObjectsEx()
, 、同じ問題を示さない場合に備えて:
DWORD ret = MsgWaitForMultipleObjectsEx(2, events, INFINITE, QS_ALLINPUT, 0);
最後に、それは大げさなかもしれませんが、後に何が起こっているのかを考えてください MsgWaitForMultipleObjects()
戻ってきて以前 GetLastError()
呼ばれています。割り当てを無視します ret
, 、暗黙の呼びかけが見えます std::wstring
'のコンストラクター。
保証できますか std::wstring
のコンストラクターには、スレッドの最後のエラーコードをクリアする副作用がありませんか?確かにできないので、電話をかけます GetLastError()
昔ながらの良い原子的割り当てに DWORD
の最初の行の変数 case
声明。