我一直在阅读,我注意到Async/Await在I/O或任何其他硬件组件上运行时不一定会创建新线程。
但是当操作被CPU限制时会发生什么呢?
public partial class Form1 : Form
{
private static List<string> _logs = new List<string>();
public Form1()
{
Print("Form constructor");
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
Print("Caller");
await SomeLongOperation();
}
private async Task SomeLongOperation()
{
Print("Called");
await Task.Delay(10000);
Print("Called after task");
}
public void Print(string txt)
{
_logs.Add($"I'm writing from thread {Thread.CurrentThread.ManagedThreadId}. And, {txt}");
}
}
假设我有这个类,如果主线程调用button1_Click方法一直运行到awaitable,然后该方法的其余部分在消息循环中排队,从而允许主线程继续工作,那么谁在运行awaitable呢,因为主线程已经在UI上工作并等待awaitable完成。
我觉得你很困惑"异步";用";平行";。
- 异步意味着线程在等待其他事情时可以腾出空间来做其他事情。这是关于您的代码如何等待
- 并行是指代码的两个部分同时运行。这只能通过多个线程来完成。这是关于您的代码如何运行
您的示例代码是异步的,但不是并行的。一切都在一根线上完成。Task.Delay
不是CPU操作。线程没有什么可做的。没有线程。
如果您确实需要运行一些CPU密集型操作,则可以使用Task.Run
将其卸载到另一个线程。例如:
await Task.Run(() => DoSomethingIntensive());
这混合了异步和并行的思想。DoSomethingIntensive()
在单独的线程上运行。这是平行的。但是主线程异步等待,这意味着它可以自由地去做其他事情(比如响应用户输入(,同时等待其他线程做自己的事情。
async
和await
关键字实际上不会导致额外的线程创建。异步方法不需要多线程,因为异步方法不在自己的线程上运行。该方法实际上在当前同步上下文上运行,并且仅当该方法处于活动状态时才在线程上使用时间。开发人员可以使用Task.Run
将绑定CPU的工作任务转移到后台线程。话虽如此,后台线程对只等待结果可用的进程没有帮助。
有关async/await
和线程的更多信息,请访问此处-https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-2.2#自动-http-400-响应-