async/await并打开FileStream?

Ale*_*nor 19 .net c# async-await .net-4.5

在尝试确定我是否正在使用Stream诸如ReadAsync并且CopyToAsync正确的方法时,我遇到了以下问题: C#4.5文件读取性能sync vs async

在这个问题中,我在接受的答案中阅读了以下内容:

最值得注意的是,您的"异步"测试不使用异步I/O; 对于文件流,您必须将它们显式地打开为异步,否则您只是在后台线程上执行同步操作.

在他的异步IO代码中,他使用以下命令打开FileStream'异步':

var file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)
Run Code Online (Sandbox Code Playgroud)

所以我想知道你是否打算使用诸如CopyToAsync是否应该FileStream如上所示打开底层的方法?而不是像下面这样做一些简单的事情:

File.Open(filename, FileMode.Open)
Run Code Online (Sandbox Code Playgroud)

这是实际文档中的示例如何CopyToAsync演示打开底层FileStream:https: //msdn.microsoft.com/en-us/library/hh159084(v = vs.110).aspx

如果底层FileStream打开的方式无关紧要,那么构造函数的useAsync参数是FileStream做什么的?

Ste*_*ary 13

所以我想知道你是否打算使用像CopyToAsync这样的方法是否应该打开底层的FileStream,如上所示?

是.原因主要是历史性的.

首先,在Windows上,HANDLE如果要OVERLAPPED对它们执行异步()操作,则必须使用异步标志显式打开/创建s(包括文件句柄).

但是,旧的Windows 95/98/ME系列支持串行端口和IOCTL(设备驱动程序)句柄上的异步操作.该平台线上不支持磁盘文件上的异步I/O. 和原来的.NET 做了支持98/ME,所以原来FileStream只是用来同步I/O.我认为(但并非绝对肯定)Win98/ME上的APM方法(例如FileStream.BeginRead)可能只是使用所谓的"异步委托"(它只是FileStream.Read在线程池线程上执行同步方法)来实现.

因此,这是文件流句柄默认情况下使用异步标志打开的历史原因.

这是CopyToAsync的实际文档中的示例如何演示

不幸的是,许多MSDN示例质量相当差.如果你从"这是一个如何调用这种特定方法的例子"的角度来看待它们,那就没关系,但从"这是使用这种方法的生产质量代码的例子"的角度来看,它们并不是那么好.


Dav*_*ine 7

所以我想知道你是否打算使用像CopyToAsync这样的方法是否应该打开如上所示的底层FileStream,而不是做一些简单的事情File.Open

我使用ILSpy进行反编译并查看File.Open.

public static FileStream Open(string path, FileMode mode)
{
    return File.Open(path, 
                     mode, 
                     (mode == FileMode.Append) 
                         ? FileAccess.Write 
                         : FileAccess.ReadWrite, 
                     FileShare.None);
}
Run Code Online (Sandbox Code Playgroud)

这称之为:

public static FileStream Open(string path, FileMode mode, FileAccess access, FileShare share)
{
    return new FileStream(path, mode, access, share);
}
Run Code Online (Sandbox Code Playgroud)

而这个特定的FileStream构造函数传入falseuseAsync参数.所以,是的,似乎很重要.但是,您仍然可以调用asyncAPI,它仍然可以按预期工作.

正如Hans Passant所说:

然后,底层CreateFile()调用使用该FILE_FLAG_OVERLAPPED选项.这启用了重叠I/O,这是一种在winapi级别启用异步读写的机制.

FileStream类有一个_isAsync布尔值,它的意思是"如果不支持在此平台上,或者此的FileStream没有与FileOptions.Asynchronous打开异步IO."

同样,你仍然得到一个Task代表你想要的异步操作.

  • 为什么在[你实际上可以查看源代码]时使用反编译器(http://referencesource.microsoft.com/#mscorlib/system/io/file.cs,1a53662a82db3651)? (2认同)