2017-01-23 5 views
3

Следующий код минимально демонстрирует проблему. В фоновом потоке я создаю допустимый массив дескрипторов и передаю его в WaitForMultipleObjects, и это успешно ждет объектов.WaitForMultipleObjects works, 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, 

РТЛ все же оборачивает эти функции по-разному. WaitForMultipleObjects использует тип указателя:

lpHandles: PWOHandleArray; 

в то время как MsgWaitForMultipleObjects использует нетипизированный var параметра:

var pHandles; 

Массив ручки должен поэтому быть передан непосредственно к MsgWaitForMultipleObjects.

т.е.

LWaitResult := MsgWaitForMultipleObjects(1, LWaitHandles, false, INFINITE, QS_ALLINPUT); 
Смежные вопросы