2017-01-23 76 views
3

以下代碼最低限度地演示了該問題。在後臺線程中,我創建了一個有效的句柄數組並將其傳遞給WaitForMultipleObjects,併成功等待對象。WaitForMultipleObjects有效,MsgWaitForMultipleObjects失敗 - 爲什麼?

然而,當將完全相同的數組傳遞給MsgWaitForMultipleObjects時,函數調用失敗(WAIT_FAILED)與ERROR_INVALID_HANDLE

我在做什麼錯?

program Project1; 
{$APPTYPE CONSOLE} 
uses 
    SysUtils, Windows, SyncObjs, Classes; 

type 
    TMyThread = class(TThread) 
    protected 
     procedure Execute; override; 
    end; 

procedure TMyThread.Execute; 
var 
    LEvent : TEvent; 
    LWaitHandles : TWOHandleArray; 
    LPWaitHandles : PWOHandleArray; 
    LWaitResult : Cardinal; 
begin 
    LEvent := TEvent.Create; 
    LWaitHandles[0] := LEvent.Handle; 
    LPWaitHandles := @LWaitHandles; 
    while not Terminated do begin 
    {Works -> LWaitResult := WaitForMultipleObjects(1, LPWaitHandles, false, INFINITE);} 
    {Fails ->} LWaitResult := MsgWaitForMultipleObjects(1, LPWaitHandles, false, INFINITE, QS_ALLINPUT); 
    case LWaitResult of 
     WAIT_OBJECT_0:  WriteLn('Event 1 Signaled'); 
     { etc... } 
     WAIT_FAILED :  WriteLn(SysErrorMessage(GetLastError)); 
    end; 
    end; 
end; 

var 
    lt : TMyThread; 
begin 
    lt := TMyThread.Create(false); 
    ReadLn; 
end. 
+0

該線程沒有消息隊列的問題?當你調用某些函數時它只會得到一個。像PeekMessage,GetMessage等不記得完整列表。 –

+0

@DavidHeffernan不,我只是想出了它 - 這是一個RTL問題(WinAPI包裝中的不穩定類型一致性)。即使沒有消息發佈到線程,「MsgWaitForMultipleObjects」仍然不會返回「WAIT_FAILED」。 –

+0

哦,我記得那個。 RTL包裝是跛腳的。另外,在你聲明一個有64個元素的數組中,沒有任何意義。你從不聲明TWOHandleArray。 –

回答

4

雖然手柄參數WinAPI的簽名是否爲這兩個調用相同:

_In_ const HANDLE *pHandles, 

的RTL仍然包裹以不同的方式這些功能。 WaitForMultipleObjects使用指針類型:

lpHandles: PWOHandleArray; 

MsgWaitForMultipleObjects使用無類型var參數:

var pHandles; 

手柄陣列因此必須直接傳遞給MsgWaitForMultipleObjects

即:

LWaitResult := MsgWaitForMultipleObjects(1, LWaitHandles, false, INFINITE, QS_ALLINPUT);