收到警报时的 GetQueuedCompletionStatusEx 行为

Posted

技术标签:

【中文标题】收到警报时的 GetQueuedCompletionStatusEx 行为【英文标题】:GetQueuedCompletionStatusEx behavior when alerted 【发布时间】:2013-09-09 03:18:52 【问题描述】:

我在 fAlertable 设置为 TRUE 的情况下使用此函数,因为我在我的框架中使用用户警报作为通用线程中断机制。根据MSDN页面上对该功能的评论,

当呼叫进入警报等待状态并且用户 APC 处于 可用于调度的返回值 GetQueuedCompletionStatusEx 为 TRUE,ulEntriesRemoved 为非零且 您的 OVERLAPPED_ENTRY 的“包”未受影响。所以如果你确保 您所有的 OVERLAPPED_ENTRY 都为其设置了一个已知的唯一值 lpOverlapped 成员,在调用 API 之前,您可以更轻松地 检测删除的条目是 APC 还是 I/O 完成数据包 通过检查 lpOverlapped 的魔法值。

为什么我需要检查所有的 OVERLAPPED_ENTRY 而不仅仅是第一个? GetQueuedCompletionStatusEx() 不会总是按顺序填充输出数组,因此我应该只检查第一个而不是循环整个数组(或至少到 ulEntriesRemoved)?此外,鉴于此函数同时使多个完成端口条目出列,是否可以保证它永远不会同时返回警报和一个或多个完成条目?我特别担心这种可能性,因为评论中指出 ulEntriesRemoved 在警报期间将不为零。尽管页面上的评论进一步提到“如果队列中有任何 I/O 完成数据包,则不会调度用户 APC。”,也许该用户仅测试了仅在用户警报之前排队的任何完成条目.

假设系统在对线程和完成端口条目的用户警报的混合中排队,然后线程运行 GetQueuedCompletionStatusEx()。从文档中,我无法确定该函数是否使此调用中的所有完成条目出列,然后每次后续调用都会发出一个用户警报(假设没有更多的完成条目排队)。鉴于文档,这似乎是最有可能的情况,但我不想做出可能被证明是错误的假设......

【问题讨论】:

【参考方案1】:

AFAIK,GetQueuedCompletionStatusEx 当用户 APC 被执行时返回 FALSE。和GetLastError() 返回WAIT_IO_COMPLETION。因此,当用户 APC 被执行时,它永远不会使任何完成数据包出队。

这是我的代码,非常适合我。

if (!::GetQueuedCompletionStatusEx(m_hIoCompletionPort, CompletionPackets, uCompletionPacketsToDequeue, &uCompletionPacketsRemoved, dwTimeToSleep, TRUE))

    DWORD dwError = ::GetLastError();

    if (dwError == WAIT_IO_COMPLETION)
    
        // User Terminate Instance.
        ATLASSERT(m_blTerminating);
        hrResult = S_OK;
        break;
    
    else if (dwError != ERROR_TIMEOUT)
    
        hrResult = HRESULT_FROM_WIN32(dwError);
        break;
    

    // One or more Timer has elapsed.
    ATLASSERT(m_Timers.GetCount() != 0);
    uCompletionPacketsRemoved = 0;

【讨论】:

对。这是 Win32 API 中发生的两种“虚假唤醒”情况之一,通常没有这种情况。更令人困惑的是,WAIT_IO_COMPLETION 与 ERROR_EXE_MARKED_INVALID 是相同的数字,当您查看返回码的含义时,这是一个很好的惊喜。

以上是关于收到警报时的 GetQueuedCompletionStatusEx 行为的主要内容,如果未能解决你的问题,请参考以下文章

红色警报 [AWS]

iPhone静音时的UILocalNotification警报

按钮更改输入时的警报文本[重复]

在日期和时间更改时重置/取消警报时的 AlarmManager 错误

将新行添加到数据库时的 Javascript 警报

使用 JQuery 选择选项时的警报下拉标签