16

为 a 执行异步 I/O 的旧 .Net 方法FileStream是使用FileStream.BeginRead()FileStream.EndRead().

状态的 MSDN 文档FileStream.BeginRead()

FileStream 提供两种不同的操作模式:同步 I/O 和异步 I/O。虽然可以使用其中任何一种,但底层操作系统资源可能只允许以其中一种模式进行访问。

默认情况下,FileStream 同步打开操作系统句柄。在 Windows 中,这会减慢异步方法的速度。如果使用异步方法,请使用 FileStream(String, FileMode, FileAccess, FileShare, Int32, Boolean) 构造函数。

.Net 4.5x为 a 执行异步 I/O 的方式是FileStream使用Stream.ReadAsync().

MSDN 文档FileStream.ReadAsync()直接链接到Stream.ReadAsync(). 该文档没有提到任何需要以异步模式打开文件;实际上,文档中的示例代码显然没有这样做。

因此,我假设使用时File.ReadAsync()无需以异步模式打开文件。

这个假设正确吗?

[编辑]

我刚刚发现了一篇关于使用 Async for File Access 的 MSDN 文章

这说明:

本主题中的示例使用 FileStream 类,该类具有导致异步 I/O 在操作系统级别发生的选项。通过使用此选项,您可以避免在许多情况下阻塞 ThreadPool 线程。

要启用此选项,请在构造函数调用中指定 useAsync=true 或 options=FileOptions.Asynchronous 参数。

所以现在我在想我应该以异步模式打开文件......如果是这样,有点不幸的是文档中提供的示例代码没有ReadAsync()异步打开文件!

4

1 回答 1

18

在 win32 中,您需要指定FILE_FLAG_OVERLAPPED才能使用异步文件 IO。在 .net 世界中,您使用isAsync参数 ofFileStream来实现相同的目的。如果您不这样做,操作将不会是异步的。

遗憾的是FileStream.ReadAsync,其相关方法未能记录下来。

您可以通过查看实现来确认这一点。

public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
   ...
    if (!this._isAsync || !Environment.IsWindowsVistaOrAbove)
    {
        return base.ReadAsync(buffer, offset, count, cancellationToken);
    }
    ...
    return stateObject;
}

base.ReadAsync最终会Stream.Read同步调用方法,ThreadPool给人的印象是操作是异步的,但实际上不是。

来自Windows 上的并发编程书籍 (Pg:818)的相关信息:

与 一样CreateFile,您必须在创建时指定要使用 FileStream 进行异步执行。使用 FileStream,您可以通过将 true 作为isAsync参数传递给接受它的构造函数重载来做到这一点。流的IsAsync 属性随后将返回 true。如果您未能传递此值,则调用BeginReadBeginWrite将成功。但是他们将使用 Stream 的基类实现,它没有提供真正异步文件 I/O 的任何好处。

以上信息是关于 APM 方法的(因为这是旧书),但仍然是相关的。

于 2014-12-08T15:01:15.673 回答