2012-12-13 60 views
1

我正在存储我的数据模型的状态。我克隆数据模型,然后想要将其写入“磁盘”异步。什么时候应该使用Task.Run()而不是等待?

我应该使用Task.Run()在后台线程上运行它吗? 或者我应该让它成为一个异步函数,而不是等待它? (这将使其在UI线程上运行)

类似的东西,这一点,但我的问题是有点不同: async Task.Run with MVVM

什么是决定其选择标准是什么?

谢谢!

回答

2

对于要在线程池线程上运行的基于CPU的工作,应该使用Task.Run

在您的情况下,您希望在不阻止用户界面的情况下执行基于I/O的工作,因此Task.Run不会为您提供任何帮助(除非您没有可用的异步I/O API)。

作为一个附注,你绝对要想要await这项工作。这使得错误处理更清晰。

所以,这样的事情应该足够了:

async void buttonSaveClick(..) 
{ 
    buttonSave.Enabled = false; 

    try 
    { 
    await myModel.Clone().SaveAsync(); 
    } 
    catch (Exception ex) 
    { 
    // Display error. 
    } 

    buttonSave.Enabled = true; 
} 
+0

谢谢。这是暂停,所以我绝对不想向用户显示任何错误。无论如何,他们无法用它做很多事情,如果它没有保存,应用程序就会恢复(如果有的话,更多的是缓存)。 – swinefeaster

0

我不认为这很重要。据我所知,这两种方法都被分派到线程池中的一个线程。

使用async让后台线程异步方法运行,并继续启动它当异步方法完成的线程上。您可以想象编译器会看到await关键字,将等待的方法放在后台线程中,并配置事件以注意异步方法完成时的注意事项。因此,如果由于成功保存而想要显示UI更改,并且因为这当然是较少的代码,所以这可能是更好的选择。

Task.Run()当你出于任何原因不希望将代码放在async方法中时会更好,例如因为您希望调用方法本身不是异步。此外,还有较少的事件编组参与,但我非常怀疑有任何性能差异。

+0

嗯...你确定吗?我认为异步的整个架构是在同一个线程上继续执行*。否则,它不会“让开发人员更容易”。 – swinefeaster

+1

来自[TAP](http://www.microsoft.com/en-us/download/details.aspx?id=19957):“如果SynchronizationContext与挂起时执行异步方法的线程相关联(例如SynchronizationContext.Current是非空的),异步方法的恢复将通过使用上下文的Post方法在同一个SynchronizationContext上发生,否则,它将依赖于任何System.Threading.Tasks.TaskScheduler当时的当前状态的暂停(通常这将是TaskScheduler.Default,其目标是.NET ThreadPool)“ – Christian

+0

这就是我所说的。异步方法的执行是从线程池执行到另一个线程,并在完成时返回调用线程,其余方法结束。 – Akku

相关问题