gpt4 book ai didi

c++ - MsgWaitForMultipleObjects 有时会返回没有 GetLastError 值的 WAIT_FAILED

转载 作者:行者123 更新时间:2023-11-30 04:37:18 29 4
gpt4 key购买 nike

我有一个创建需要单线程单元的 COM 对象的线程。

本来这个线程的main函数把它放到了一个WaitForMultipleObjects循环中。显然这是一个问题,因为它阻止了 COM 消息泵完成它的工作。

我用 MsgWaitForMultipleObjects 替换它作为解决方案,但现在我遇到了一个问题:MsgWaitForMultipleObjects 有时(经常)返回 WAIT_FAILED,但没有设置错误。

代码通过继续并尝试再次调用 MsgWaitForMultipleObjects 来处理 WAIT_FAILED 返回值。对 MsgWaitForMultipleObjects 的调用可能会返回 WAIT_FAILED 几次(我见过的最多是 9 次),但随后它突然可以正常工作了。

如果函数出于正当理由返回 WAIT_FAILED,则编写代码可能会进入无限循环。我知道我应该解决这个问题,但目前我认为这是一个“变通办法”,因为 MsgWaitForMultipleObjects 调用最终会成功。

此代码正在 Windows 7、Vista 和 XP(所有 32 位、Windows 7 32 位和 64 位)上进行测试。

有人知道为什么会这样吗?

相关代码:

bool run = true;
while (run)
{
DWORD ret = MsgWaitForMultipleObjects(2, events, FALSE, INFINITE,
QS_ALLINPUT);

switch (ret)
{
case WAIT_OBJECT_0:
{
ResetEvent(events[0]);
ProcessWorkQueue();
break;
}

case WAIT_OBJECT_0 + 1:
{
run = false;
break;
}

case WAIT_OBJECT_0 + 2:
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
DispatchMessage(&msg);
break;
}

case WAIT_FAILED:
{
Logger::Output(L"Wait failed in Notify::Run(), error is "
+ boost::lexical_cast<std::wstring>(GetLastError()));
}
}
}

示例输出为:

Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
// At this point, the wait succeeds

我相信 WAIT_FAILED 返回值仅在等待被消息中断后发生。

最佳答案

这不应该发生,我肯定无法解释它发生的确切原因。不过,我确实有一些建议。

首先,您没有在消息泵中的 DispatchMessage() 之前调用 TranslateMessage()。那是糟糕的 juju,你不希望 MsgWaitForMultipleObjects() 附近的任何地方发生糟糕的 juju。

您可能还想尝试显式调用 MsgWaitForMultipleObjectsEx(),以防它不会出现相同的问题:

DWORD ret = MsgWaitForMultipleObjectsEx(2, events, INFINITE, QS_ALLINPUT, 0);

最后,这可能有些牵强,但请考虑在 MsgWaitForMultipleObjects() 返回之后和调用 GetLastError() 之前发生的情况。忽略对 ret 的赋值,我看到对 std::wstring 的构造函数的隐式调用。

你能保证 std::wstring 的构造函数没有清除线程最后一个错误代码的副作用吗?我肯定不能,所以我将对 GetLastError() 的调用移动到对第一行中的 DWORD 变量的一个好的、老式的原子赋值中case 语句。

关于c++ - MsgWaitForMultipleObjects 有时会返回没有 GetLastError 值的 WAIT_FAILED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3945003/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com