2015-02-23 88 views
9

我想了解什么是调用异步方法更新我的ViewModel时使用的最佳方法。 现在,让我们说我有这样的事情:使用MVVM模式实现异步“loadData”方法的最佳方法

查看:

private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e) 
{ 
    //Call my ViewModel method to update the data the UI is bound to   
} 

视图模型:

public async Task loadData() 
{ 
    this.Source = await loadStuffFromDatabaseAsync(); 
} 

现在,我不知道这下面的一个我应该使用的方法:

1)在我LoadState的方法,使用方法:

await Task.Run(async() => { await ViewMode.loadData(); }); 

2)使用 Task.Run 而不等待 行动 内 loadData 方法:

await Task.Run(() => { ViewModel.loadData(); }); 

3)呼叫我的 loadData 方法:

await ViewModel.loadData().ConfigureAwait(false); 

4)调用 loadData 方法,无需等待它在我的 View类 和使用 Task.Run 我loadData方法中:

查看:

private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e) 
{ 
    ViewModel.loadData(); 
} 

查看型号:

public async void loadData() 
{ 
    await Task.Run(async() => 
    { 
     this.Source = await loadStuffFromDatabaseAsync(); 
    }); 
} 

这些认可的主要区别是什么?

另一个更有效率,我应该特别选择一个吗?

感谢您的帮助! :)

塞尔吉奥

+0

异步void的方法,你应该遵循附加异步所有异步方法的命名约定。 – 2015-02-23 20:35:01

+0

我认为,由于Asynch支持集成到基本代码中的是Async和Await两个词,因此我相信Reed Cosby已经告诉我们所有我们需要的东西。我们不再需要调用任务方法。 – 2015-02-23 20:51:40

+2

@JohnPeters:事实并非如此。可能有阻塞UI线程的代码。 – Fred 2015-02-23 21:25:18

回答

2

,才应使用Task.Run,如果你有CPU绑定或阻塞,你要搬出去,UI线程的工作。这不是这种情况,所以直接电话(选项3)是最自然的。

以它们依次是:

await Task.Run(async() => { await ViewMode.loadData(); }); 

此选项将在一个线程池线程执行loadData。这可能不太好,因为loadData正在更新UI(间接通过设置VM属性)。即使它确实发生了工作(即,某些MVVM框架可以在某些情况下正确处理来自后台线程的更新),但可能不必要,因为loadData是一种异步方法。

此外,它无故增加了状态机开销async

await Task.Run(() => { ViewModel.loadData(); }); 

此选项都是一样的问题,只是因为它不具备async状态机的开销,这会更有效。但它仍然在后台线程上更新虚拟机属性,并且不必要地使用后台线程。

public async void loadData() 

这是最糟糕的。它继承了其他问题:在后台线程上更新VM属性并使用不必要的后台线程。为此它增加了async void的问题。一个问题是NavigationHelper_LoadState无法捕捉到来自loadData的任何异常。另一个问题是loadData不容易测试。

所以只需使用简单的方法,直接把它叫做:应避免

await ViewModel.loadData().ConfigureAwait(false); 
+0

谢谢你的回答!我只是有一个疑问:你说我应该只使用Task.Run进行CPU绑定或阻塞工作:为什么不从数据库中加载数据作为阻塞工作?由于它是一个IO操作,可能需要很长时间才能完成,因此阻止正在等待该任务的调用方法? – Sergio0694 2015-02-23 22:40:12

+1

线程未被阻止,因为它是异步操作。 – 2015-02-23 23:15:44

+0

你是对的,通过“阻止工作”你的意思是一些同步代码运行。再次感谢你的帮助 :) – Sergio0694 2015-02-23 23:19:46