重叠I/O的GetOverlappedResult(bWait=TRUE)与WaitForSingleObject()

重叠I/O的GetOverlappedResult(bWait=TRUE)与WaitForSingleObject(),c,windows,winapi,C,Windows,Winapi,当我在Win32 api上以重叠方式打开和读取文件时,我有几种方法来完成IO请求,包括使用等待文件句柄(或重叠结构中的事件) WaitForSingleObject GetOverlappedResult,bWait=TRUE 这两个函数似乎具有相同的效果:线程在句柄或事件发出信号之前停止,这意味着数据被放置在提供给ReadFile的缓冲区中 那么,有什么区别呢?为什么我需要GetOverlappedResult?您可以使用这两种方法,但这确实不是“正确”的方法。您应该将句柄连接到IO完成端

当我在Win32 api上以重叠方式打开和读取文件时,我有几种方法来完成IO请求,包括使用等待文件句柄(或重叠结构中的事件)

  • WaitForSingleObject
  • GetOverlappedResult
    ,bWait=TRUE
这两个函数似乎具有相同的效果:线程在句柄或事件发出信号之前停止,这意味着数据被放置在提供给
ReadFile
的缓冲区中


那么,有什么区别呢?为什么我需要
GetOverlappedResult

您可以使用这两种方法,但这确实不是“正确”的方法。您应该将句柄连接到IO完成端口,然后等待完成端口。这样,您就有了一个线程池来为许多IO事件提供服务,因为您可以将多个句柄附加到一个完成端口。我推荐阅读。

我完全同意雷姆斯·鲁萨努的观点。此外,还可以创建自己的IOCP和线程池,它们将在此IOCP上侦听,您可以使用or或(从vista开始)-在这种情况下,系统自己创建IOCP和线程池,它将在此IOCP上侦听,当某些操作完成时-调用您的回调。这是非常简单的代码与自己的iocp/线程池(我认为自己的iocp/线程池只有在拥有大量i/O(比如服务器端的套接字io)并且需要针对性能进行特殊优化时才有意义地实现)

然而

那么,有什么区别呢?为什么我需要GetOverlappedResult

如何查看
GetOverlappedResult[Ex]
不仅等待结果,而且

  • 如果操作完成,则返回NumberOfByTestTransferred
  • 如果操作已完成,但出现错误NTSTATUS-请将其转换为win32 错误并设置最后一个错误
  • 如果操作仍处于挂起状态,而您希望等待,请选择等待 hFile或hEvent
因此,
GetOverlappedResult[Ex]
所做的不仅仅是调用
WaitForSingleObject

但是,自己实现这个API不是很难。比如说

BOOL
WINAPI
MyGetOverlappedResult(
                    _In_ HANDLE hFile,
                    _In_ LPOVERLAPPED lpOverlapped,
                    _Out_ LPDWORD lpNumberOfBytesTransferred,
                    _In_ BOOL bWait
                    )
{
    if ((NTSTATUS)lpOverlapped->Internal == STATUS_PENDING)
    {
        if (!bWait)
        {
            SetLastError(ERROR_IO_INCOMPLETE);
            return FALSE;
        }

        if (lpOverlapped->hEvent)
        {
            hFile = lpOverlapped->hEvent;
        }

        if (WaitForSingleObject(hFile, INFINITE) != WAIT_OBJECT_0)
        {
            return FALSE;
        }
    }
    else
    {
        MemoryBarrier();
    }

    *lpNumberOfBytesTransferred = (ULONG)lpOverlapped->InternalHigh;
    NTSTATUS status = (NTSTATUS)lpOverlapped->Internal;
    if (status)
    {
        RtlNtStatusToDosError(status);
    }
    return NT_SUCCESS(status);
}

那么还有什么更好的方法:使用
GetOverlappedResult[Ex]
或者自己实现它的功能?

谢谢,但我的I/O操作不会超过2个,所以我不确定我是否需要IO完成端口。我知道它们和其他方法,如可变IO(APC)。我的问题是关于区别:)@user996142使用IO完成端口总是比使用
GetOverlappedResult
等待要好。对于I/O操作的任何计数,您也可以通过或@RbMm间接使用它。在一般情况下,我100%同意IOCP将优于重叠IO。我所知道的一个例外是全双工串行IO。根据“阅读和写作”一节中的“非重叠IO”小节,注意,如果不使用重叠IO,串行端口上不可能进行全双工通信。@dgnuff-IOCP将优于重叠IO-重叠I/O-这是异步I/O。这意味着文件句柄在异步模式下打开-带有标志
file\u flag\u overlapped
(如果我们使用
CreateFile
)或者如果我们使用ZWAPI,则没有
文件\u同步\u IO\u[NON]警报
标志。
IOCP
只能在文件句柄为的情况下与之关联(查看1550行)。所以你的评论是不正确的。IOCP不是io类型。这是另一个问题。并且只能与重叠的IOShort版本一起使用:
WaitForSingleObject
不会告诉您操作是成功还是失败,如果它碰巧是一种I/O,可能处理的字节数比您要求的要少,您也不会知道。