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

问题描述

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

解决方法

一种常见的方法是编写一个从 Win32 (WSA)OVERLAPPED 结构派生或将 (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;
}