2017-01-23 3 views
3

Le code suivant illustre le problème de manière minimale. Dans un thread d'arrière-plan, je crée un tableau de handles valide et le passe à WaitForMultipleObjects et cela attend avec succès sur les objets.WaitForMultipleObjects fonctionne, MsgWaitForMultipleObjects échoue - pourquoi?

Lors du passage du même tableau à MsgWaitForMultipleObjects, cependant, l'appel de fonction échoue (WAIT_FAILED) avec ERROR_INVALID_HANDLE.

Qu'est-ce que je fais mal?

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

Est-ce le problème que le fil ne dispose pas d'une file d'attente de messages? Il n'en obtient qu'un lorsque vous appelez certaines fonctions. Comme PeekMessage, GetMessage, etc. Je ne me souviens pas de la liste complète. –

+0

@DavidHeffernan Non, je l'ai juste compris - c'est un problème RTL (cohérence de type erratique dans les wrappers WinAPI). Même si aucun message n'est publié sur le thread, 'MsgWaitForMultipleObjects' ne doit toujours pas renvoyer' WAIT_FAILED'. –

+0

Oh, je m'en souviens. L'encapsuleur RTL est boiteux. De plus, il est inutile de déclarer un tableau avec 64 éléments comme ça. Vous ne déclarez jamais un TWOHandleArray. –

Répondre

4

Bien que la signature WinAPI pour le paramètre poignées est identique pour ces deux appels:

_In_ const HANDLE *pHandles, 

RTL enveloppements néanmoins ces fonctions de différentes manières. WaitForMultipleObjects utilise le type de pointeur:

lpHandles: PWOHandleArray; 

tandis que MsgWaitForMultipleObjects utilise un paramètre var typées:

var pHandles; 

Le tableau de poignée doit donc être transmis directement à MsgWaitForMultipleObjects.

-à-dire:

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