【问题标题】:async Task is freezing the UI异步任务正在冻结 UI
【发布时间】:2012-09-26 18:06:56
【问题描述】:

我有这样的方法:

private async Task DoSomething()
{
    // long running work here.
}

当我这样调用方法时,它会阻塞 UI:

Task t = DoSomething();

我必须执行其中一项以使其成为非阻塞:

Task t = new Task(() => DoSomething());
t.Start();

// Or

Task t = Task.Factory.StartNew(() => DoSomething());

那么,当您可以像在框架 4 中一样使用任务并使用 Task.Wait() 代替 await 时,异步 / 等待的意义何在?

编辑: 我理解你所有的答案——但没有一个能真正解决我的最后一段。谁能给我一个基于任务的多线程示例,其中 async / await 提高了程序的可读性和/或流程?

【问题讨论】:

  • async 的目的不是多线程。它用于异步编程。您可以使用Task.Run进行多线程,但async 也可以与其他异步操作(例如I/O)一起使用。基于任务的异步模式非常强大,因为它可以以相同的方式处理任何异步操作(无论是 CPU 密集型、I/O 密集型还是其他)。

标签: c# .net-4.5 async-await


【解决方案1】:

您如何使用await?这不会阻止 UI:

    private async Task DoSomething()
    {
        await Task.Delay(5000);
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        await DoSomething();
        MessageBox.Show("Finished");
    }

请注意,我不必编写任何冗长的回调内容。这就是async/await的意义所在。

【讨论】:

  • 这不会阻塞 UI,因为 Task.Delay 使用在 ThreadPool 上运行的 System.Threading.Timer。尝试使用 Thread.Sleep(5000),您会看到 UI 阻塞。
  • 顺便说一句,通过使用异步您不需要创建线程的想法在我看来是完全的 BS。 await 只能应用于返回 Task 或 Task 的方法这一事实显然表明,在某些时候有人将不得不创建一个新的 Task!
  • @BrunoSantos 正确,为你 +1,因为提到了System.Threading.Timer
【解决方案2】:

async 方法开始同步执行。 async 对于编写异步操作很有用,但它不会神奇地让代码在另一个线程上运行,除非你告诉它。

您可以使用 Task.Run 将 CPU 密集型工作安排到线程池线程。

请查看我的async / await intro postasync FAQ 了解更多信息。

【讨论】:

    【解决方案3】:

    如果没有实际代码,很难告诉您发生了什么,但您可以使用“await Task.Yield();”开始您的 DoSomething强制它立即返回,以防在第一次等待之前运行的内容是导致您的 UI 问题的原因。

    【讨论】:

      猜你喜欢
      • 2015-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 1970-01-01
      相关资源
      最近更新 更多