为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()
文档中提供的示例代码确实如此不异步打开文件!
答案 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
财产随后将返回真实。如果你没有通过这个 价值,对BeginRead
和BeginWrite
的调用都会成功。但是他们 将使用Stream提供的基类实现 没有真正的异步文件I / O的好处。
以上信息是关于APM方法(因为这是旧书),但仍然是相关的。