WaitForSingleObject()在完成端口上?

时间:2016-09-20 20:06:46

标签: winapi io-completion-ports

今天我了解到我可以致电CreateIoCompletionPort(),然后将退回的HANDLE传递给WaitForSingleObject()

#include <Windows.h>

int main()
{
    HANDLE h = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
    auto bRes = PostQueuedCompletionStatus(h, 1, 2, 0);
    if (!bRes) {
        abort();
    }

    auto dwRes = WaitForSingleObject(h, INFINITE);
    if (dwRes != WAIT_OBJECT_0){
        abort();
    }

    LPOVERLAPPED pOvr;
    DWORD cb;
    ULONG_PTR key;
    bRes = GetQueuedCompletionStatus(
        h, &cb, &key, &pOvr, INFINITE); // <-- returns 1, 2, nullptr

    if (!bRes) {
        abort();
    }

    dwRes = WaitForSingleObject(h, INFINITE); // <-- blocks here
    return 0;
}

它在我的Windows 10盒子上按预期工作。

这种行为是已知的还是合法的还是有记录的?我无法找到任何相关信息。

2 个答案:

答案 0 :(得分:3)

如果您阅读WaitForSingleObject() documentation,则I / O完成端口 NOT 是允许的句柄类型:

  

WaitForSingleObject函数可以等待以下对象:

     
      
  • 更改通知
  •   
  • 控制台输入
  •   
  • 事件
  •   
  • 内存资源通知
  •   
  • 互斥
  •   
  • 过程
  •   
  • 信号量
  •   
  •   
  • 等待计时器
  •   

要等待完成事件到达端口,您必须自己将句柄传递给GetQueuedCompletionStatus()并让它阻塞,直到事件到达或发生超时。

#include <Windows.h>

int main()
{
    HANDLE h = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
    auto bRes = PostQueuedCompletionStatus(h, 1, 2, 0);
    if (!bRes) {
        abort();
    }

    LPOVERLAPPED pOvr;
    DWORD cb;
    ULONG_PTR key;
    bRes = GetQueuedCompletionStatus(
        h, &cb, &key, &pOvr, INFINITE); // <-- returns 1, 2, nullptr

    if (!bRes) {
        abort();
    }

    bRes = GetQueuedCompletionStatus(
        h, &cb, &key, &pOvr, INFINITE); // <-- blocks here

    return 0;
}

答案 1 :(得分:1)

摘要:

  • 不要这样做。请参阅Remy Lebeau的回答和MSDN,了解如何正确使用完成端口。
  • 此类滥用完工港口不仅没有证件,而且不可靠。行为因Windows 10的构建而异。
  • 完成端口可能是内核中等待的合法对象,因为支持完成端口的KQUEUE具有DISPATCHER_HEADER。