同步和重叠输入和输出

可以对文件、命名管道和串行通信设备执行同步或异步(也称为重叠)I/O作。 WriteFileReadFileDeviceIoControlWaitCommEventConnectNamedPipe,以及 TransactNamedPipe 函数可以同步或异步执行。 ReadFileExWriteFileEx 函数只能异步执行。

同步执行函数时,在作完成之前不会返回该函数。 这意味着,在等待耗时的作完成时,可以无限期阻止调用线程的执行。 调用重叠作的函数可以立即返回,即使尚未完成该作。 这样就可以在后台执行耗时的 I/O作,同时调用线程可以自由执行其他任务。 例如,单个线程可以在不同的句柄上同时执行 I/O作,甚至可以在同一句柄上同时执行读写作。

若要将其执行与重叠作的完成同步,调用线程使用 GetOverlappedResult 函数、GetOverlappedResultEx 函数或 等待函数之一 来确定重叠作何时完成。 还可以使用 HasOverlappedIoCompleted 宏轮询完成。

若要取消所有挂起的异步 I/O作,请使用 CancelIoEx 函数,并提供指定取消请求的 OVERLAPPED 结构。 使用 CancelIo 函数取消由指定文件句柄的调用线程颁发的挂起的异步 I/O作。

重叠作需要使用 FILE_FLAG_OVERLAPPED 标志创建的文件、命名管道或通信设备。 当线程调用函数(如 ReadFile 函数)来执行重叠作时,调用线程必须指定指向 OVERLAPPED 结构的指针。 (如果此指针 NULL,则函数返回值可能错误地指示作已完成。除非使用事件来指示 I/O作完成,否则 重叠 结构的所有成员都必须初始化为零。 如果使用事件,则 hEventOVERLAPPED 结构的成员指定已分配的事件对象的句柄。 当对 I/O 函数的调用在作完成之前返回时,系统将事件对象的状态设置为非对齐状态。 系统将事件对象的状态设置为在作完成后发出信号。 仅当同时有多个未完成的 I/O作时,才需要一个事件。 如果未使用事件,则每个已完成的 I/O作都会向文件、命名管道或通信设备发出信号。

调用函数以执行重叠作时,该作可能在函数返回之前完成。 发生这种情况时,会像同步执行作一样处理结果。 但是,如果未完成作,则函数的返回值 FALSE,并且 getLastError函数返回 ERROR_IO_PENDING

线程可以通过以下两种方法之一管理重叠作:

  • 使用 GetOverlappedResultGetOverlappedResultEx 函数等待重叠的作完成。 如果使用 GetOverlappedResultEx,则调用线程可以指定重叠作的超时或执行可警报等待。
  • 等待函数之一中指定 OVERLAPPED 结构的手动重置事件对象的句柄,然后在等待函数返回后,调用 GetOverlappedResultGetOverlappedResultEx。 该函数返回已完成的重叠作的结果,对于信息适当的函数,它将报告传输的实际字节数。

在单个线程上执行多个同时重叠的作时,调用线程必须为每个作指定 OVERLAPPED 结构。 每个 重叠 结构都必须为不同的手动重置事件对象指定句柄。 若要等待任一重叠作完成,线程将指定所有手动重置事件句柄作为多对象 等待函数之一的等待条件。 多对象等待函数的返回值指示哪个手动重置事件对象已发出信号,因此线程可以确定哪个重叠作导致等待作完成。

为每个重叠作使用单独的事件对象更安全,而不是指定任何事件对象或为多个作重复使用同一事件对象。 如果在 OVERLAPPED 结构中未指定任何事件对象,则系统在完成重叠作时向文件、命名管道或通信设备的状态发出信号。 因此,可以在等待函数中将这些句柄指定为同步对象,尽管它们用于此目的可能难以管理,因为在同一文件、命名管道或通信设备上执行同时重叠的作时,无法知道哪个作导致对象的状态发出信号。

线程不应重复使用事件,假设该事件仅由该线程的重叠作发出信号。 事件在正在完成的重叠作所在的同一线程上发出信号。 在多个线程上使用同一事件可能会导致一个争用条件,在该条件中,该事件为该线程发出正确的信号,该线程的作首先完成,并且对于使用该事件的其他线程来说为过早。 然后,当下一个重叠作完成时,将使用该事件的所有线程再次向事件发出信号,依此指示,直到所有重叠作完成为止。

有关说明使用重叠作、完成例程和 GetOverlappedResult 函数的示例,请参阅 使用管道

Windows Vista、Windows Server 2003 和 Windows XP:

重用 重叠 结构时请小心。 如果在多个线程上重复使用 重叠 结构,并且 GetOverlappedResult 调用,bWait 参数设置为 TRUE,则调用线程必须确保在重用结构之前发出关联的事件信号。 这可以通过在 调用 getOverlappedResult 后使用 WaitForSingleObject 函数来强制线程等待作完成。 请注意,事件对象必须是手动重置事件对象。 如果使用了 autoreset 事件对象,则调用 GetOverlappedResult,并将 bWait 参数设置为 TRUE 会导致函数无限期被阻止。 此行为从 Windows 7 和 Windows Server 2008 R2 开始更改,适用于将 Windows 7 指定为应用程序清单中支持的作系统的应用程序。 有关详细信息,请参阅 应用程序清单

I/O 概念