使用StreamReader.ReadToEndAsync(),await不会按预期返回到调用者

时间:2017-06-13 09:34:01

标签: c# .net asynchronous

尝试了解流和async/await。如果我正确地await将执行返回给调用者,那么我希望下面代码的结果是:

before calling async ReadToEnd
after the call to ReadToEnd
before calling async ReadToEnd
after the call to ReadToEnd

但是它确实是

before calling async ReadToEnd
after the call to ReadToEnd
before calling async ReadToEnd
after await in ReadToEnd. streamReader.BaseStream.GetType(): System.IO.MemoryStream
after the call to ReadToEnd

在调用StreamReader时,使用FileStream下面带有StreamReader.ReadToEndAsync()的{​​{1}}实际上会返回给调用方,但是当StreamReader与{一起使用}时它不起作用{1}}下面。

试图了解发生了什么我已经阅读了.NET源代码,并得出结论,在MemoryStream下面调用StreamReader.ReadToEndAsync()最终会调用MemoryStream({{3在BaseStream上。在ReadAsync()的情况下,MemoryStream实际上不是一个异常的方法,因此不会返回给调用者。

我的理解是否正确?

ReadAsync()

2 个答案:

答案 0 :(得分:5)

await 只有等待未完成同步的 才会将执行返回给调用者。是的,async方法可以选择同步完成,因为:

  • 他们已经知道答案(缓存结果,缓冲数据,已知故障状态等)
  • 他们没有合适的异步下游操作来执行

MemoryStream 总是同步,所以它总是这样做。

相比之下,

FieStream 可能会或可能不会同步完成,具体取决于缓冲区中可用的数据等。

关于是否返回来电者的决定由GetAwaiter().IsCompleted推动,(Task)归结为.IsCompleted

答案 1 :(得分:2)

在代码的第一部分中,您要从StreamReader创建File。当你调用streamReader.ReadToEndAsync()时,必须首先从硬盘驱动器读取文件到内存,然后才能返回内容,这是异步完成的。

在代码的第二部分中,您要从StreamReader创建MemoryStreambytes是从streamReader.ReadToEndAsync()构建的,已经加载到应用程序的内存中。在这种情况下,ng-class会立即返回内容,因为数据在内存中,可以立即获取。