async / await并打开FileStream?

时间:2016-05-05 03:31:14

标签: c# .net async-await .net-4.5

在尝试确定我是否正确使用StreamReadAsyncCopyToAsync方法时,我遇到了以下问题: C# 4.5 file read performance sync vs async

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

  

最值得注意的是,您的" async" test不使用异步I / O;与文件   stream,你必须明确地将它们打开为异步或其他   你只是在后台线程上做同步操作。

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

var file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)

所以我想知道你是否打算使用诸如CopyToAsync之类的方法是否应该打开如上所示的基础FileStream,而不是像下面那样做一些简单的事情:

File.Open(filename, FileMode.Open)

CopyToAsync的实际文档中的示例如何演示打开基础FileStreamhttps://msdn.microsoft.com/en-us/library/hh159084(v=vs.110).aspx

如果打开基础FileStream的方式无关紧要,useAsync构造函数的FileStream参数有什么作用?

3 个答案:

答案 0 :(得分:13)

  

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

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

首先,在Windows上HANDLEs (including file handles) must be opened/created explicitly with an asynchronous flag if you want to do asynchronous (OVERLAPPED) operations on them

然而,the old Windows 95/98/ME line only supported asynchronous operations on serial port and IOCTL (device driver) handles。该平台线上不支持磁盘文件上的异步I / O.并且the original .NET did support 98/ME,原来的FileStream只使用了同步I / O.我认为(但并非绝对确定)Win98 / ME上的APM methods(如FileStream.BeginRead)可能只是使用所谓的"asynchronous delegates"实现的(Postman REST Client只需在线程池线程上执行FileStream.Read之类的同步方法。

因此,这是文件流处理默认情况下使用异步标志打开而不是的历史原因。

  

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

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

答案 1 :(得分: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);
}

这称之为:

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

此特定FileStream构造函数在false中传递useAsync参数。所以,是的,似乎很重要。但是,您仍然可以调用async API,它仍然可以按预期工作。

正如Hans Passant所说:

  

然后,基础CreateFile()调用使用FILE_FLAG_OVERLAPPED选项。这样就可以重叠 I / O ,这是一种在winapi级别启用异步读写的机制。

FileStream类具有_isAsync bool,这意味着“如果此平台不支持异步IO,或者未使用FileOptions.Asynchronous打开此FileStream。”。

同样,您仍然可以获得一个代表该异步操作的Task

答案 2 :(得分:2)

The MSDN website说:

  

useAsync

     

输入:System.Boolean

     

指定是使用异步I / O还是同步I / O.   但是,请注意底层操作系统可能不支持   异步I / O,因此在指定true时,可能会打开句柄   同步取决于平台。异步打开时,   BeginReadBeginWrite方法在大型方面表现更好   读取或写入,但对于小读取或写入,它们可能要慢得多   写道。如果应用程序旨在利用   异步I / O,将useAsync参数设置为true。运用   异步I / O正确可以加快应用程序的速度   因子为10,但在没有重新设计申请的情况下使用它   异步I / O可以将性能降低多达一倍   10。