首页 > 解决方案 > GetQueuedCompletionStatus - 如何识别已完成任务的“类型”?

问题描述

能否请您告诉我,当完成端口队列中出现就绪任务时,然后使用 GetQueuedCompletionStatus 函数检索它,您如何知道该就绪任务是用于读取还是写入?

标签: c++cwinapiwinsockwinsock2

解决方案


一种常见的方法是编写一个从 Win32 结构派生的(WSA)OVERLAPPED结构,或者将 a(WSA)OVERLAPPED作为其第一个数据成员。然后,您可以将其他数据成员添加到您的结构中,以根据需要识别其任务、跟踪其状态等。

然后,您可以为每个 I/O 操作分配一个结构实例,根据需要填充它,并将指向它的(WSA)OVERLAPPED*指针作为指向您选择的 I/O 函数的指针传递。

当 I/O 完成返回时,您可以将提供OVERLAPPED*的指针类型转换为指向您的结构类型的指针以访问其成员。

例如:

enum MY_OP_TYPE { opReading, opWriting };

struct MY_STRUCT : OVERLAPPED // or WSAOVERLAPPED
{
    MY_OP_TYPE opType;
    // other data members as needed...

    MY_STRUCT()
    {
        Internal = 0;
        InternalHigh = 0;
        Offset = 0;
        OffsetHigh = 0;
        hEvent = NULL;
        // other initializations as needed...
    }

    ~MY_STRUCT()
    {
        // cleanups as needed...
        // free hEvent if it is a (WSA)Event object...
    }

    // other methods as needed...
};
MY_STRUCT *ms = new MY_STRUCT;
ms->opType = opReading;
ms->hEvent = ...; // depending on which I/O function you are using, this could be a (WSA)Event object, or a pointer to opaque app data, etc...
// other assignments as needed...
...

if (IoReadingFunction(..., static_cast<OVERLAPPED*>(ms), ...) == FALSE /* or SOCKET_ERROR */)
{
    if (GetLastError() != ERROR_IO_PENDING)
    // or
    // if (WSAGetLastError() != WSA_IO_PENDING) 
    {
        ...
        delete ms;
    }
}
...
OVERLAPPED *ov;
...

GetQueuedCompletionStatus(..., &ov, ... );
if (ov)
{
    MY_STRUCT *ms = static_cast<MY_STRUCT*>(ov);
    // use ms as needed...

    switch (ms->opType)
    {
        ...
    }

    ...

    delete ms;
}

推荐阅读