试图理解流和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()似乎确实会返回给调用方,但是当使用下面有MemoryStream的StreamReader时,它就不能工作了。
为了理解正在发生的事情,我阅读了.NET源代码,并得出了这样的结论:用下面的MemoryStream调用StreamReader.ReadToEndAsync()最终会调用BaseStream上的ReadAsync() (来源)。对于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());
}
}发布于 2017-06-13 09:53:11
只有在等待的事情没有同步完成时,await才会将执行返回给调用方。是的,如果async方法选择,它们可以同步完成,原因之一是:
MemoryStream总是同步的,所以它总是这样做的。
相反,FileStream可能同步完成,也可能不同步完成,这取决于缓冲区中可用的数据,等等。
是否返回调用方的决定是由GetAwaiter().IsCompleted驱动的,它(对于Task)可以归结为.IsCompleted。
发布于 2017-06-13 09:53:03
在代码的第一部分中,您将从StreamReader创建File。当您调用streamReader.ReadToEndAsync()时,必须先将文件读入硬盘驱动器的内存中,然后才能返回内容,这是异步完成的。
在代码的第二部分中,您将从MemoryStream创建MemoryStream,它是从已经加载到应用程序内存中的bytes构建的。在这种情况下,streamReader.ReadToEndAsync()会立即返回内容,因为数据在内存中,可以立即获取。
https://stackoverflow.com/questions/44517607
复制相似问题