在尝试确定我是否正确使用Stream
和ReadAsync
等CopyToAsync
方法时,我遇到了以下问题:
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
的实际文档中的示例如何演示打开基础FileStream
:
https://msdn.microsoft.com/en-us/library/hh159084(v=vs.110).aspx
如果打开基础FileStream
的方式无关紧要,useAsync
构造函数的FileStream
参数有什么作用?
答案 0 :(得分:13)
所以我想知道你是否打算使用像CopyToAsync这样的方法是否应该打开底层的FileStream,如上所示?
是。原因主要是历史性的。
然而,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)
useAsync
指定是使用异步I / O还是同步I / O. 但是,请注意底层操作系统可能不支持 异步I / O,因此在指定
true
时,可能会打开句柄 同步取决于平台。异步打开时, BeginRead和BeginWrite方法在大型方面表现更好 读取或写入,但对于小读取或写入,它们可能要慢得多 写道。如果应用程序旨在利用 异步I / O,将useAsync
参数设置为true
。运用 异步I / O正确可以加快应用程序的速度 因子为10,但在没有重新设计申请的情况下使用它 异步I / O可以将性能降低多达一倍 10。