isp*_*iro 1 .net c# multithreading asynchronous async-await
Task在提出这个问题后,我一直在阅读有关s 的内容,发现我完全误解了这个概念。此处 和此处的最佳答案等答案 解释了这个想法,但我仍然不明白。\n所以我提出了一个非常具体的问题:CPU 上实际发生了什么执行任务时
这是我在阅读后了解到的:任务将与调用者共享 CPU 时间(假设调用者是“UI”),因此如果它是 CPU 密集型的,那么它会变慢下用户界面。如果任务不是CPU密集型的 - 它将“在后台”运行。在测试之前似乎足够清楚 \xe2\x80\xa6\xe2\x80\xa6 。下面的代码应该允许用户单击按钮,然后交替显示“已显示”和“按钮”。但实际上:表单完全繁忙(无法进行用户输入),直到“已显示”全部显示为止。
\n\npublic Form1()\n{\n InitializeComponent();\n Shown += Form1_Shown;\n}\n\nprivate async void Form1_Shown(object sender, EventArgs e)\n{\n await Doit("Shown");\n}\n\nprivate async Task Doit(string s)\n{\n WebClient client = new WebClient();\n for (int i = 0; i < 10; i++)\n {\n client.DownloadData(uri);//This is here in order to delay the Text writing without much CPU use.\n textBox1.Text += s + "\\r\\n";\n this.Update();//textBox1.\n }\n}\n\nprivate async void button1_Click(object sender, EventArgs e)\n{\n await Doit("Button");\n}\nRun Code Online (Sandbox Code Playgroud)\n\n有人可以告诉我执行任务时CPU上实际发生了什么(例如“当UI不使用CPU时,任务使用它,除了\xe2\x80\xa6等”)?
\n理解这一点的关键是,有两种任务- 一种执行代码(我称之为委托任务),另一种代表未来事件(我称之为 Promise 任务)。这两个任务完全不同,尽管它们都由 .NET 中的实例表示Task。我的博客上有一些漂亮的图片,可能有助于理解这些类型的任务有何不同。
Task.Run委托任务是由朋友创建的任务。它们在线程池(或者TaskScheduler如果您使用的是另一个线程池TaskFactory)上执行代码。大多数“任务并行库”文档都涉及委托任务。它们用于将 CPU 密集型算法分散到多个 CPU 上,或将 CPU 密集型工作从 UI 线程中推送出去。
TaskCompletionSource<T>Promise 任务是由和 朋友(包括)创建的任务async。这些是用于异步编程的,并且非常适合 I/O 密集型代码。
请注意,您的示例代码将导致编译器警告,大意是您的“异步”方法Doit实际上不是异步的,而是同步的。所以现在的情况是,它会同步调用DownloadData,阻塞 UI 线程,直到下载完成,然后更新文本框,最后返回一个已经完成的任务。
要使其异步,您必须使用await:
private async Task Doit(string s)
{
WebClient client = new WebClient();
for (int i = 0; i < 10; i++)
{
await client.DownloadDataTaskAsync(uri);
textBox1.Text += s + "\r\n";
this.Update();//textBox1.
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当它点击 时,它会返回一个未完成的任务await,这允许 UI 线程返回到其消息处理循环。下载完成后,此方法的其余部分将作为消息排队到 UI 线程,并且当它有时间时将继续执行该方法。当该Doit方法完成时,它之前返回的任务将完成。
因此,方法返回的任务async在逻辑上代表该方法。任务本身是一个 Promise Task,而不是一个 Delegate Task,并且实际上并不“执行”。该方法被分成多个部分(在每个await点)并分块执行,但任务本身不在任何地方执行。
为了进一步阅读,我有一篇关于如何async和await实际工作(以及它们如何调度方法块)的博客文章,以及另一篇关于为什么异步 I/O 任务不需要阻塞线程的博客文章。