C# 如何为“wait DoSthAsync”安排线程
输出: 3:从文件中读取 1:从字符串读取 1:主线程 上面,为什么从文件读取会产生一个新线程,而不是从字符串读取 更具体地说,为什么异步文件IO需要一个新线程来完成 它只是底层同步文件IO的包装版本,然后通过生成新线程来调度它吗 为什么从文件读取会产生一个新线程,而不是从字符串读取 让我在这里澄清一下,这两个调用都没有产生新的线程——事实上,没有创建新的线程,或者正如我的朋友斯蒂芬·克利里喜欢说的那样 为什么异步文件IO需要一个新线程来完成 现在,线程标识符不同的原因是,其中一个调用实际上使文件保持打开状态。我创建了一个实例,演示了无论是否正确地等待异步调用完成,线程id仍然会更改。线索隐藏在StreamReader的源代码中。.ctorstring路径最终会在leaveOpen参数上传递true,而.ctorStream则会在该参数上传递false。看看这两个构造函数路径 引用上述文章: 由于library/BCL使用的是标准的P/Invoke重叠I/O系统,因此它已经向I/O完成端口IOCP注册了句柄,IOCP是线程池的一部分。因此,短暂借用一个I/O线程池线程来执行APC,它会通知任务它已经完成 更新 我只是再次运行,结果如下:C# 如何为“wait DoSthAsync”安排线程,c#,async-await,.net-core,C#,Async Await,.net Core,输出: 3:从文件中读取 1:从字符串读取 1:主线程 上面,为什么从文件读取会产生一个新线程,而不是从字符串读取 更具体地说,为什么异步文件IO需要一个新线程来完成 它只是底层同步文件IO的包装版本,然后通过生成新线程来调度它吗 为什么从文件读取会产生一个新线程,而不是从字符串读取 让我在这里澄清一下,这两个调用都没有产生新的线程——事实上,没有创建新的线程,或者正如我的朋友斯蒂芬·克利里喜欢说的那样 为什么异步文件IO需要一个新线程来完成 现在,线程标识符不同的原因是,其中一个调用实际上使文
这似乎告诉我的一件事是,由于实际写入文件系统的两个操作实际上是I/O绑定的操作,而另一个操作只是在内存中。不确定这是否有助于澄清问题?我猜简单的答案是,既然从内存流中读取数据没有本质上的异步性,没有真正的工作要发送给其他线程。您正在寻找的是关于C中的async/await功能的完整教程。您应该使用您最喜欢的web搜索引擎来查找描述这些关键字的一篇或多篇文章。不过,前面的评论总结了这里的具体行为:从内存中对象的读取可以同步完成,因此您永远不会出现在不同的线程中。+1我几乎感觉堆栈溢出应该要求任何发布[c][async await]问题的人都必须在发布之前阅读没有线程。我用这篇文章回答的问题数量之多让我难以置信。即使ctor被更改为通过新的StreamReaderFile.Createtest.txt接收FileStream,新线程仍然会被创建。我看到了预期的行为,下面是…@David谢谢。我拉了你的小提琴,所以得到了59 59 142 142。我等59岁?142! 142! 142!. 我的测试结果是59142,但预期是142。Stephen的文章有助于澄清关于线程和AIO的误解。嗯,它非常需要代码演示。
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static void Main(string[] args)
{
Read(File.OpenText("test.txt")); // content: "read from file"
Read(new StreamReader(new MemoryStream(
Encoding.UTF8.GetBytes("read from string")));
Console.WriteLine("{0}: {1}",
Thread.CurrentThread.ManagedThreadId, "main thread");
Console.ReadKey();
}
static async Task Read(StreamReader sr)
{
var s = await sr.ReadToEndAsync();
Console.WriteLine("{0}: {1}",
Thread.CurrentThread.ManagedThreadId, s);
}
}