使用FileStream.ReadAsync()时,我应该以异步模式打开文件吗?

时间:2014-12-08 14:31:41

标签: c# async-await filestream beginread

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

FileStream.BeginRead()州的MSDN文档:

  

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

     

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

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

FileStream.ReadAsync()的MSDN文档直接链接到Stream.ReadAsync()的文档。本文档未提及在异步模式下打开文件的任何需要;实际上,文档中的示例代码显然不会这样做。

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

这个假设是否正确?

[编辑]

我刚刚发现了an MSDN article on using Async for File Access

这表明:

  

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

     

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

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

1 个答案:

答案 0 :(得分:17)

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

遗憾的是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方法,给人的印象是操作是异步的,但实际上并非如此。

Concurrent Programming On Windows书中的相关信息(Pg:818):

  

CreateFile一样,您必须在创建时指定您   喜欢使用FileStream进行异步执行。同   FileStream,您可以通过将isAsync参数传递给true来实现此目的   构造函数重载,接受它。流的IsAsync   财产随后将返回真实。如果你没有通过这个   价值,对BeginReadBeginWrite的调用都会成功。但是他们   将使用Stream提供的基类实现   没有真正的异步文件I / O的好处。

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