2010-10-15 31 views
1

我有一個線程可以創建需要單個線程單元的COM對象。MsgWaitForMultipleObjects有時會返回WAIT_FAILED而沒有GetLastError值

最初,這個線程的主函數把它放到一個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返回值僅發生。

+0

嗯,我不知道誰給了你使用MsgWaitForMultipleObjects的想法。那麼,希望他會訪問這個線程。 – 2010-10-15 18:39:14

回答

2

這應該不會發生,我當然不能解釋它確實爲什麼它。不過,我確實有幾點提示。

首先,您不要在消息泵中調用DispatchMessage()之前的TranslateMessage()。這是不好的juju,並且你不想要壞的juju在MsgWaitForMultipleObjects()附近的任何地方。

您也可能想嘗試顯式調用MsgWaitForMultipleObjectsEx(),以防萬一它不表現出了同樣的問題:

DWORD ret = MsgWaitForMultipleObjectsEx(2, events, INFINITE, QS_ALLINPUT, 0); 

最後,它可能是牽強,但考慮什麼是後MsgWaitForMultipleObjects()返回之前發生調用GetLastError()。忽略對ret的分配,我看到一個隱含的對std::wstring的構造函數的調用。

你能保證std::wstring的構造函數沒有一些副作用來清除線程的最​​後一個錯誤代碼嗎?我當然不能,因此我會將GetLastError()的電話轉換爲case聲明第一行中DWORD變量的良好的老式原子分配。

+0

感謝您的回覆。我省略了'TanslateMessage',因爲它不應該處理任何關鍵消息,但我加了它以防萬一。'GetLastError'保證在'std :: wstring'構造之前被調用,但是我預先存儲了這個值。沒有解決這個問題,但我會嘗試使用Ex版本。 – 2010-10-15 20:19:23

+0

對不起,作爲一個便箋,我知道'GetLastError'沒有被設置,因爲我有時可以看到它有一個值,這意味着'文件沒有找到',我知道這是設置。其他時候,它返回0. – 2010-10-15 20:28:43

+0

'Ex'版本解決了它,謝謝。 – 2010-10-15 20:31:58

相關問題