【问题标题】:GetOverlappedResultEx will create a thread to process on or do I have to create and sync the threads?GetOverlappedResultEx 将创建一个线程来处理还是我必须创建和同步线程?
【发布时间】:2021-05-08 06:30:03
【问题描述】:

试图了解这是如何工作的...我是否必须创建各种线程才能利用 GetOverlappedResultEx 的功能?但是,为什么我不能将 GetOverlappedResult 放在与主线程不同的线程中,以处理 IO 阻塞而不干扰主操作?

GetOverlappedResult 函数

https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getoverlappedresult

检索对指定文件、命名管道或通信设备的重叠操作的结果。要指定超时间隔或等待警报线程,请使用 GetOverlappedResultEx。

https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getoverlappedresultex

在指定的超时间隔内检索对指定文件、命名管道或通信设备的重叠操作的结果。调用线程可以执行警报等待。

https://docs.microsoft.com/en-us/windows/win32/fileio/alertable-i-o

【问题讨论】:

  • 你自己做。但是如果您在同一个线程上同时查看多个异步操作,请查看I/O Completion Ports 以了解如何有效地执行此操作。 (虽然最好先在没有 I/O 完成端口的情况下进行实验/学习,只是为了了解发生了什么,然后再将它们添加到组合中。)
  • GetOverlappedResultEx 不创建任何线程,而是等待 I/O 完成并返回最终状态

标签: windows winapi visual-c++


【解决方案1】:

您自己处理线程,以实现并发性。

基本上有三种方法:

  1. 启动重叠(即异步完成)I/O 操作后,您执行其他操作,然后每隔一段时间轮询句柄以查看重叠操作是否已完成。这就是您可以使用GetOverlappedResult 查找STATUS_PENDING 来查看操作是否尚未完成的方法。

  2. 您坐在那里等待重叠操作完成。但这并没有那么糟糕,因为您实际上可以坐在那里等待一组重叠操作中的任何一个完成。一旦任何一个完成,你就处理它,然后循环等待其余的。当然,处理它可能会触发 another 异步操作,您可以将该句柄添加到列表中。这是您使用WaitForSingleObject{Ex} 或更好的WaitForMultipleObjects{Ex} 的地方。

  3. 您使用 I/O 完成端口。在这里,您将一些句柄传递给称为 I/O 完成端口的内核对象——这个内核对象巧妙地将线程池(它自己管理)与回调结合起来。这是一种非常有效的方式,可以同时处理多个——实际上是非常多的——异步操作。在这些回调中,您可以做任何您想做的事情,包括启动更多异步操作并将它们添加到同一个 I/O 完成端口。

还有第四个概念:可警报 I/O,它在启动 I/O 的线程上的“APC”上执行回调,前提是您的线程处于“可警报”状态 - 这意味着它正在执行在内核中等待的一个或另一个特定 API。但是我从来没有使用过它,因为它似乎有缺点(例如只在启动 I/O 的线程上工作,并且回调环境运行的环境不是尽可能清晰),如果只要找出 I/O Completion 端口并使用它们,您就会走得那么远。

选项 #2 和 #3 当然涉及并发编程 - 因此在这两种情况下,您必须确保您的回调相对于其他线程是线程安全的。

在 intertubes 上有很多所有这些方法的例子。

【讨论】:

  • 3 有 2 个子选项 - 使用 BindIoCompletionCallbackCreateThreadpoolIo。它在内部将文件绑定到系统管理的 iocp。结果不需要自己创建iocp,也不需要创建线程池,从iocp弹出数据包。或者可以自己做(创建 iocp 和监听池)。
  • 关于 APC 完成 - 是的,当然 apc 只在线程中调用,它开始 I/O。但回调环境绝对清楚。而且很多win32 api都没有办法设置apc回调。根本没有参数。尽管内部原生 api 当然总是有这样的参数。在某些情况下,apc 回调可能是非常有用且很好的解决方案
  • 我在可警报 I/O 方面有很好的经验。有时它非常适合用例。它不仅减轻了 WaitForMultipleObjects 可以等待的对象的限制,而且它也比较容易使用,假设一个线程,因为您不需要处理 WaitForMultipleObjects API 并确定哪个对象通过索引发出信号等等。甚至异步 Windows API 也不会立即返回;例如,ReadFileEx 可能需要几毫秒。如果你不能做到这一点,那么使用可警报 I/O 专门为它设置一个线程会很有意义。
  • @Dico - 关于警报 I/O 的有趣观察(对于可以立即返回的异步 API 的立即返回 - 或至少比异步变种更快。
猜你喜欢
  • 2017-05-09
  • 1970-01-01
  • 2019-08-16
  • 2013-02-08
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多