【问题标题】:WaitForMultipleObjects works, MsgWaitForMultipleObjects fails - why?WaitForMultipleObjects 有效,MsgWaitForMultipleObjects 失败 - 为什么?
【发布时间】:2017-01-23 17:35:04
【问题描述】:

以下代码最低限度地演示了该问题。在后台线程中,我创建了一个有效的句柄数组并将其传递给WaitForMultipleObjects,这会成功等待对象。

但是,当将完全相同的数组传递给 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.

【问题讨论】:

  • 是线程没有消息队列的问题吗?当您调用某些函数时,它只会得到一个。像 PeekMessage、GetMessage 等。不记得完整列表了。
  • @DavidHeffernan 不,我只是想通了 - 这是一个 RTL 问题(WinAPI 包装器中的类型一致性不稳定)。即使没有消息发布到线程,MsgWaitForMultipleObjects 仍不应返回WAIT_FAILED
  • 哦,我记得。 RTL 包装器是蹩脚的。此外,声明一个包含 64 个元素的数组也没有任何意义。你永远不会声明一个 TWOHandleArray。
  • @DavidHeffernan 是的,我没有费心制作消息队列,因为它对于演示问题并不重要。是的,TWOHandleArray 很浪费——不过,它确实为 MCVE 节省了一行代码。
  • TWOHandleArray 很好。如果我注意 RTL 包装器,我就不会问this 问题。

标签: multithreading delphi winapi delphi-10-seattle


【解决方案1】:

虽然这两个调用的句柄参数的 WinAPI 签名是相同的:

 _In_ const HANDLE *pHandles,

RTL 以不同的方式包装这些函数。 WaitForMultipleObjects 使用指针类型:

lpHandles: PWOHandleArray;

MsgWaitForMultipleObjects 使用无类型的var 参数:

var pHandles;

因此必须将句柄数组直接传递给MsgWaitForMultipleObjects

即:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 2020-04-11
    • 1970-01-01
    相关资源
    最近更新 更多