GetQueuedCompletionStatus - 如何识别已完成任务的“类型”?

GetQueuedCompletionStatus - how to identify the “type” of the finished task?

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

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

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

当 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;
}