C# 为什么CPU绑定的代码将GUI锁定在async\await中而不是IO绑定?

C# 为什么CPU绑定的代码将GUI锁定在async\await中而不是IO绑定?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,根据微软的文章,对于CPU绑定的任务最好使用线程,对于IO绑定的任务最好使用异步\等待。另一方面,一些post-like说:如果您谈论的是使用异步操作,那么async/await对于I/O绑定和CPU绑定都非常有效。 我知道Async\Await只使用当前上下文(单个当前线程),当遇到耗时的命令时,它会将控制权返回给主叫方,直到得到答案 根据以上信息,我尝试在DotNet Windows应用程序中使用以下代码测试Sync\Wait: class SampleClass { public

根据微软的文章,对于CPU绑定的任务最好使用线程,对于IO绑定的任务最好使用异步\等待。另一方面,一些post-like说:如果您谈论的是使用异步操作,那么async/await对于I/O绑定和CPU绑定都非常有效。 我知道Async\Await只使用当前上下文(单个当前线程),当遇到耗时的命令时,它会将控制权返回给主叫方,直到得到答案

根据以上信息,我尝试在DotNet Windows应用程序中使用以下代码测试Sync\Wait:

class SampleClass
{
    public  async Task<double> TestAsync()
    {
         HttpClient client = new HttpClient();

        Task<double> doIt =  DoWork();

        double result = await doIt;

        return result;  
    }

     private async Task<double> DoWork()
    {
        //Line24: It takes a 4-sec CPU-Bound task and locks GUI when running
        TimeConsumingCPUBound();

        //Line27: It takes a 10-sec IO-Bound task and doesn't lock GUI when running
        await Task.Delay(10000);

        return 0;
    }

    public void TimeConsumingCPUBound()
    {
        string x = "";
        for (int i = 0; i < 50000; i++)
        {
            x = x + i.ToString();
        }
    }
}
我的问题是,为什么在第24行(CPU绑定)GUI被锁定,而在第27行(IO绑定)不是吗? 我原以为在这两种情况下,GUI都是免费的

如“您可以使用Task.Run将CPU绑定的工作移动到后台线程”中所述:

private async Task DoWork()
{
等待任务。运行(()=>TimeConsumingPubound());
等待任务。延迟(10000);
返回0;
}

谢谢,但为什么我的问题看起来很糟糕?我不知道是谁投了反对票,也不知道为什么。谢谢,任务。运行新线程?不是吗?我可以归纳为异步吗(没有任务?运行,只是在IO绑定中工作,有IO延迟?我将阅读您的nicearticle@Mohammad:
Task.Run
将工作排队到线程池,因此其委托将在线程池线程上运行。@Mohammad:
wait
将在其任务未完成时返回调用方。在您的示例中,
DoWork
执行CP“我知道Async\Await只使用当前上下文(单个当前线程),当遇到耗时的命令时,它会将控制权返回给主调用者,直到得到答案。”@TheodorZoulias我根据本文()这说明async和await关键字不会导致创建额外的线程。异步方法不需要多线程,因为异步方法不在自己的线程上运行。Mohammad这段文档中的引用是正确的,但它如何验证您关于“耗时命令”的陈述?“耗时”并不意味着“异步”IMHO。同步、阻塞操作也可能很耗时。我的意思是
Task
s或其他可等待的内容(例如
ValueTask
s),它们的
IsCompleted
属性在您等待它们时等于
false
。这就是导致异步状态机将继续项装箱并将控件返回给调用方的原因。否则(如果任务已完成)该方法不会返回,而是继续运行,直到下一个
wait
,或者直到该方法结束。@TheodorZoulias感谢朋友的澄清。
 private async void button1_Click(object sender, EventArgs e)
    {
        SampleClass d = new SampleClass();
        await d.TestAsync();

    }
private async Task<double> DoWork()
{
  await Task.Run(() => TimeConsumingCPUBound());

  await Task.Delay(10000);

  return 0;
}