c# - await 不会按预期使用 StreamReader.ReadToEndAsync() 返回给调用者

标签 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.ReadToEndAsync() 时,使用带有 FileStreamStreamReader 确实返回给调用者,但它确实将 StreamReader 与下面的 MemoryStream 一起使用时不起作用。

为了了解发生了什么,我阅读了 .NET 源代码并得出结论,最终使用 MemoryStream 调用 StreamReader.ReadToEndAsync()在 BaseStream 上调用 ReadAsync() ( source )。在 MemoryStream 的情况下,ReadAsync() 并不是真正的异步方法,因此不会返回给调用者。

我的理解正确吗?

using System;
using System.Text;
using System.Linq;
using System.IO;
using System.Threading.Tasks;

static class Program
{
    public static void Main(string[] args)
    {
        var longString = new string(Enumerable.Repeat('x', 100000000).ToArray());
        File.WriteAllText("bigFile.txt", longString, Encoding.UTF32);

        StreamReader fileStreamReader = new StreamReader(File.OpenRead(@"bigFile.txt"));
        Console.WriteLine("before calling async ReadToEnd");
        var task = ReadToEnd(fileStreamReader);
        Console.WriteLine("after the call to ReadToEnd");

        byte[] bytes = Encoding.UTF32.GetBytes(longString);
        StreamReader memoryStreamReader = new StreamReader(new MemoryStream(bytes));
        Console.WriteLine("before calling async ReadToEnd");
        var task2 = ReadToEnd(memoryStreamReader);
        Console.WriteLine("after the call to ReadToEnd");

        fileStreamReader.Dispose();
        memoryStreamReader.Dispose();
    }

    static async Task ReadToEnd(StreamReader streamReader)
    {
        string allText = await streamReader.ReadToEndAsync();
        Console.WriteLine("after await in ReadToEnd. streamReader.BaseStream.GetType(): " + streamReader.BaseStream.GetType());
    }
}

最佳答案

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

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

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

FileStream,相比之下,可能会也可能不会同步完成,这取决于缓冲区中可用的数据等。

关于是否返回调用者的决定由 GetAwaiter().IsCompleted 驱动,它(对于 Task)归结为 .IsCompleted

关于c# - await 不会按预期使用 StreamReader.ReadToEndAsync() 返回给调用者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44517607/

相关文章:

c# - 为每个 appender 创建不同的 log4net.ILog 实例

.net - 如何使用静态成员创建.NET接口(interface)?

javascript - 循环中的异步回调

C# 文件/文件夹监视器

c# - 如何在没有 ASPX 的情况下在 C# 中创建 Web 框架?

c# - HttpClient 和 ASP.NET Core 2.0 web 服务之间的连接已关闭错误

java - Spring拦截返回异步调用

c# - 嵌套 Async Await 不等待

c# - 在 ASP.NET Core 3.1/5.0 中调用存储过程

c# - asp.net中的用户桌面屏幕录制