2017-01-23 29 views
3

次のコードは、この問題を最小限に示しています。バックグラウンドスレッドでは、有効なハンドル配列を作成し、それをWaitForMultipleObjectsに渡すと、オブジェクトが正常に待機します。WaitForMultipleObjectsが動作し、MsgWaitForMultipleObjectsが失敗します - なぜですか?

ただし、同じ配列をMsgWaitForMultipleObjectsに渡すと、ERROR_INVALID_HANDLEで関数呼び出しが失敗します(WAIT_FAILED)。

私は間違っていますか?

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のシグネチャは、これら2つの呼び出しのために同じであるが:

_In_ const HANDLE *pHandles, 

RTLは、それにもかかわらず、様々な方法でこれらの機能をラップします。ハンドルアレイしたがってMsgWaitForMultipleObjectsに直接渡されなければならない

var pHandles; 

MsgWaitForMultipleObjectsは型なしvarパラメータを使用しながら

lpHandles: PWOHandleArray; 

WaitForMultipleObjectsはポインタ型を使用します。

すなわち:

LWaitResult := MsgWaitForMultipleObjects(1, LWaitHandles, false, INFINITE, QS_ALLINPUT); 
関連する問題