-2

首先,EndRead 的文档没有明确说明由 BeginRead 发起的异步读取操作是原子的或不可中断的。

问题

是否可以中断由 FileStream.BeginRead 启动的异步读取操作,以便它在填充缓冲区之前完成,返回到目前为止读入缓冲区的字节数,还是全有或全无操作?

换句话说,是否有一些像“Cancel_IO”这样的方法可以调用,这样当我调用 EndRead 时,不是等待读取所有可能的字节,而是由于读取被取消而更早返回?

背景

我已经阅读了 FileStream、BeginRead 和 EndRead 的文档。EndRead 没有任何能够触发操作过早完成的重载,返回部分已满的缓冲区。我感兴趣的是是否有人可以确认或否认 Windows 操作系统 API (Win32) 或磁盘驱动程序 API 中存在的方法,这可能导致 FileStream.BeginRead 启动的操作在 EndRead 时提前完成叫。“早期”是指在填充整个请求的缓冲区长度之前,没有错误。

用例

出于想象力的考虑,假设文件位于网络共享上,并且网络有时可能会遇到极端的减速,因此触发提前完成通用 1MB 缓冲操作将是实用且最佳的,以便检索在恢复新的 1MB 缓冲操作之前处理几个字节。

这些“几个字节”可用于启动大量计算密集型内存资源的构建,这些资源可以在允许缓冲完成时构建。

关于文档

请注意,BeginRead 的文档没有明确说明异步操作是原子的还是不可中断的。它所提到的是,如果发生“错误”,在调用 EndRead 之前您不会知道它。这并不排除可能发生其他一些不是错误的事件,这会导致 EndRead 返回的字节数少于请求的字节数,无论如何它一直都会这样做。

例如,“文件结束”和“缓冲区已满”可以看作是异步读取操作的两个“自然”中断,这会导致它返回的字节数少于请求的字节数,而不会出错。我正在寻找“人为”中断的可能性,这也会导致 EndRead 在 EOF 之前和缓冲区已满之前成功返回读入缓冲区的字节数。

4

3 回答 3

2

文档明确指出:必须使用此 IAsyncResult 调用 EndRead 以找出读取了多少字节。另一方面,EndRead正在阻塞线程,直到读取操作完成。所以,看起来读操作是原子的。

这对我来说是合乎逻辑的,因为您的场景有一些实际用途。如果有价值的信息存储在正在读取的文件的一部分中,那么您总是可以以较小的部分读取它。

于 2011-08-29T03:41:06.960 回答
0

不; 没有 API 可以做到这一点。

关闭手柄是一个古老的技巧 - 它可以追溯到 NT 时代。但是,它会导致句柄上所有未完成的操作以错误完成。

取消也有类似的问题 - 请注意,CancelIoEx您的平台上可能不可用。

SetCommTimeouts不是一个选项,因为它仅适用于串行端口和其他通信设备句柄。

取消一直是编写设备驱动程序最困难的部分之一。现在,内核在 XP 中内置了 Cancel-Safe Queue 支持(可向后移植到 2K),而且要容易得多。但是很多司机(尤其是老司机)无论如何都会忽略取消(这是合法的)。

我建议在更高的抽象级别实现“取消”:关闭句柄或允许操作完成,并忽略结果。

于 2011-09-02T14:09:37.953 回答
0

我在windows 同步和异步 I/O的文档中阅读了一些内容,这可能会起到作用,但这将是一个具有不确定后果的技巧。

“如果句柄被提前释放,ReadFile 或 WriteFile 可能会错误地报告 I/O 操作已完成。”

由于 .NET BeginRead 方法最终基于 Win32 ReadFile 方法,因此获取和过早释放句柄可能会完成我想要做的事情。其后果将需要研究。

它还提到“要取消所有挂起的异步 I/O 操作,请使用:CancelIoCancelIoEx ”,但这些操作似乎会以失败 (ERROR_OPERATION_ABORTED) 取消整个操作。我不确定读取的任何字节是否已经写入缓冲区,即使是,也不知道有多少字节被成功写入。我想知道是否有办法诱使底层系统认为它突然到达文件或流的末尾......

我还看到“ SetCommTimeouts ”方法有一些有趣的结果,特别是围绕“ COMMTIMEOUTS Structure的”“ReadIntervalTimeout” 成员,它声称:

“如果任何两个字节到达的时间间隔超过了这个量,ReadFile 操作就完成了,任何缓冲的数据都会被返回。”

这似乎很有希望...

在任何情况下,我可以取消挂起的异步 I/O 本身就很有用。实际上,我可以使用缓冲统计信息和开始时间来计算是否值得取消异步读取并重新发出对所需数据块的较小读取,或者等待操作完成是否更好。这将取决于计算的流的平均速度,以及它与完成的距离(基于它的计算/预测的进度值)和预期的完成时间,并根据获得所需数据块的相对效用进行加权。

于 2011-08-29T05:39:18.623 回答