GetOverlappedResultEx 将创建一个线程来处理,还是我必须创建并同步线程?
GetOverlappedResultEx will create a thread to process on or do I have to create and sync the threads?
试图了解这是如何工作的...我是否必须创建各种线程才能利用 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 操作后,您执行其他操作,然后每隔一段时间轮询句柄以查看重叠操作是否已完成。这是您可以使用 GetOverlappedResult
查找 STATUS_PENDING
以查看操作是否尚未完成的方法。
您坐等重叠操作完成。但这并没有那么糟糕,因为您实际上可以坐在那里等待一组重叠操作中的任何一个完成。一旦有人完成你处理它,然后循环等待其余的。当然,处理它可能会触发 另一个 异步操作,您将该句柄添加到列表中。这是您使用 WaitForSingleObject{Ex}
或更好的 WaitForMultipleObjects{Ex}
.
的地方
您使用 I/O 完成端口。在这里,您将一些句柄传递给称为 I/O 完成端口的内核对象 - 这个内核对象巧妙地将线程池(它自己管理)与回调结合在一起。这是一种非常有效的方式来处理同时进行中的多个(事实上,非常多)异步操作。在这些回调中,您可以做任何您想做的事情,包括启动更多异步操作并将它们添加到相同的 I/O 完成端口。
还有第四个概念:alertable I/O,它在启动 I/O 的线程上的“APC”上执行回调,前提是您的线程处于“alertable”状态- 这意味着它正在执行在内核中等待的某些 API 中的一个或另一个。但是我从来没有使用过它,因为它似乎有缺点(例如只在启动 I/O 的线程上工作,并且回调环境运行的环境并不那么清晰)如果你打算走那么远,只需找出 I/O 完成端口并使用它们。
选项 #2 和 #3 当然涉及并发编程 - 因此在这两种情况下,您都必须确保您的回调相对于其他线程是线程安全的。
所有这些方法在 intertubes 上有很多例子。
试图了解这是如何工作的...我是否必须创建各种线程才能利用 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 操作后,您执行其他操作,然后每隔一段时间轮询句柄以查看重叠操作是否已完成。这是您可以使用
GetOverlappedResult
查找STATUS_PENDING
以查看操作是否尚未完成的方法。您坐等重叠操作完成。但这并没有那么糟糕,因为您实际上可以坐在那里等待一组重叠操作中的任何一个完成。一旦有人完成你处理它,然后循环等待其余的。当然,处理它可能会触发 另一个 异步操作,您将该句柄添加到列表中。这是您使用
的地方WaitForSingleObject{Ex}
或更好的WaitForMultipleObjects{Ex}
.您使用 I/O 完成端口。在这里,您将一些句柄传递给称为 I/O 完成端口的内核对象 - 这个内核对象巧妙地将线程池(它自己管理)与回调结合在一起。这是一种非常有效的方式来处理同时进行中的多个(事实上,非常多)异步操作。在这些回调中,您可以做任何您想做的事情,包括启动更多异步操作并将它们添加到相同的 I/O 完成端口。
还有第四个概念:alertable I/O,它在启动 I/O 的线程上的“APC”上执行回调,前提是您的线程处于“alertable”状态- 这意味着它正在执行在内核中等待的某些 API 中的一个或另一个。但是我从来没有使用过它,因为它似乎有缺点(例如只在启动 I/O 的线程上工作,并且回调环境运行的环境并不那么清晰)如果你打算走那么远,只需找出 I/O 完成端口并使用它们。
选项 #2 和 #3 当然涉及并发编程 - 因此在这两种情况下,您都必须确保您的回调相对于其他线程是线程安全的。
所有这些方法在 intertubes 上有很多例子。