【问题标题】:Running long tasks without freezing the UI在不冻结 UI 的情况下运行长时间任务
【发布时间】:2012-04-21 08:11:48
【问题描述】:

我正在尝试在后台执行一项操作,而不冻结 UI。

当然,我可以为此使用 BackgroundWorker。

但是,我只想使用 Task API 来完成。

我试过了:

async void OnTestLoaded(object sender, RoutedEventArgs e)
{
   await LongOperation();
}
// It freezes the UI

async void OnTestLoaded(object sender, RoutedEventArgs e)
{
   var task = Task.Run(()=> LongOperation());
   task.Wait();
}


// It freezes the UI

那么我应该回到BackgroundWorker 吗?或者是否有仅使用任务的解决方案?

【问题讨论】:

  • 为什么这么多人不喜欢BackgroundWorker?我喜欢它,直接找到语法。
  • BackgroundWorker 远好于Thread,但基于Task 的API 最终将占据主导地位。我有a related blog postTask.Run具有以下优点:(1)允许嵌套; (2)取消支持使用统一的CancellationToken系统; (3) 使用正确的调用堆栈更自然地传播异常; (4) 检索结果更自然; (5) 使用更少的资源(线程池而不是专用线程)。

标签: wpf task microsoft-metro


【解决方案1】:

你已经很接近了。

async void OnTestLoaded(object sender, RoutedEventArgs e)
{
  await Task.Run(() => LongOperation());
}

asyncdoes not execute a method on a thread pool thread.

Task.Run 在线程池线程上执行操作并返回代表该操作的Task

如果您在async 方法中使用Task.Wait,您就是doing it wrong。您应该在async 方法中使用await 任务,永远不要阻止它们。

【讨论】:

  • 如果你在这个具体的例子中不使用 async 或 await 会有什么不同吗?
  • @Lukazoid:如果你的意思是Task.Run 没有await,那么它会默默地吞下来自LongOperation 的所有异常。
  • 但不会因为OnTestLoadedasync void 而吞下异常吗?啊,从进一步阅读来看,似乎在使用async void时,异常会在开始时捕获的SynchronizationContext上重新抛出,没有async/await,它会像你说的那样被吞掉,对吗?
猜你喜欢
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-15
  • 2012-08-07
相关资源
最近更新 更多