代码之家  ›  专栏  ›  技术社区  ›  Collin Dauphinee

msgwaitformultipleobjects有时返回wait_failed,没有getLastError值

  •  1
  • Collin Dauphinee  · 技术社区  · 14 年前

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

    最初,该线程的主函数将其放入WaitForMultipleObjects循环。显然,这是一个问题,因为它阻止了COM消息泵完成它的工作。

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

    代码通过继续并再次尝试调用msgwaitformultipleobjects来处理wait_failed返回值。对msgwaitformultipleobjects的调用可能会返回wait_失败几次(我看到的最多是9次),但随后它会突然正常工作。

    编写代码的目的是,如果函数返回wait_失败的原因是有效的,那么这可能会进入无限循环。我知道我应该解决这个问题,但现在我正在考虑“解决问题”,因为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返回值只在wait被消息破坏之后发生。

    1 回复  |  直到 14 年前
        1
  •  2
  •   Frédéric Hamidi    14 年前

    这不应该发生,我也不能确切解释 为什么? 是的。不过,我确实有一些建议。

    首先,你没有打电话 TranslateMessage() 之前 DispatchMessage() 在你的信息泵里。那是坏的juju,你不想在附近的任何地方坏juju MsgWaitForMultipleObjects() .

    您也可以尝试显式调用 MsgWaitForMultipleObjectsEx() 以防出现同样的问题:

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

    最后,这可能有些牵强,但考虑一下之后会发生什么。 msgwaitformultipleObjects()。 返回和之前 GetLastError() 被称为。不考虑分配给 ret ,我看到一个隐式调用 std::wstring 的构造函数。

    你能保证吗 STD:: 的构造函数没有清除线程上一个错误代码的副作用?我当然不能,所以我把电话转到 GETLASTROR() 变成一个好的,老式的,原子的任务 DWORD 变量位于 case 语句。