wpf 使用 MVVM 模式实现异步“loadData”方法的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28682836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to implement an async "loadData" method using the MVVM pattern
提问by Sergio0694
I'm trying to understand what is the best approach to use when calling an async method that updates my ViewModel. Right now, let's say I have something like this:
我试图了解在调用更新我的 ViewModel 的异步方法时使用的最佳方法是什么。现在,假设我有这样的事情:
View:
看法:
private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
//Call my ViewModel method to update the data the UI is bound to
}
ViewModel:
视图模型:
public async Task loadData()
{
this.Source = await loadStuffFromDatabaseAsync();
}
Now, I'm not sure which one of the following approaches should I use:
现在,我不确定应该使用以下哪一种方法:
1)In my LoadState method, use:
1)在我的 LoadState 方法中,使用:
await Task.Run(async () => { await ViewMode.loadData(); });
2)Use Task.Run without awaiting the loadData method inside the Action :
2)使用 Task.Run 而不等待 Action 中的 loadData 方法:
await Task.Run(() => { ViewModel.loadData(); });
3)Call my loadData method with:
3)调用我的 loadData 方法:
await ViewModel.loadData().ConfigureAwait(false);
4)Call the loadData method without awaiting it in my View class and use Task.Run inside my loadData method:
4)调用 loadData 方法而不在我的 View 类中等待它并在我的 loadData 方法中使用 Task.Run :
View:
看法:
private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
ViewModel.loadData();
}
ViewModel:
视图模型:
public async void loadData()
{
await Task.Run(async () =>
{
this.Source = await loadStuffFromDatabaseAsync();
});
}
What are the main differences between these approaces?
这些方法之间的主要区别是什么?
Is one more efficient that the other, and should I pick one in particular?
一个比另一个更有效吗,我应该特别选择一个吗?
Thanks for your help! :)
谢谢你的帮助!:)
Sergio
塞尔吉奥
采纳答案by Stephen Cleary
You should only use Task.Runif you have CPU-bound or blocking work that you want to move off the UI thread. That's not the case here, so the direct call (option 3) is the most natural.
仅Task.Run当您有希望从 UI 线程移出的受 CPU 限制或阻塞的工作时才应使用。这里不是这种情况,所以直接调用(选项 3)是最自然的。
Taking them in turn:
依次拿他们:
await Task.Run(async () => { await ViewMode.loadData(); });
This option will execute loadDataon a thread pool thread. This may not work very well, since loadDatais updating the UI (indirectly by setting a VM property). Even if it does happen to work (i.e., some MVVM frameworks can properly handle updates from background threads in some scenarios), it's probably unnecessary since loadDatais an asynchronous method.
此选项将loadData在线程池线程上执行。这可能效果不佳,因为loadData正在更新 UI(通过设置 VM 属性间接更新)。即使它确实有效(即,某些 MVVM 框架在某些情况下可以正确处理来自后台线程的更新),也可能没有必要,因为它loadData是一种异步方法。
Furthermore, it adds asyncstate machine overhead for no reason.
此外,它async无缘无故地增加了状态机开销。
await Task.Run(() => { ViewModel.loadData(); });
This option has all the same problems, except it's slightly more efficient since it doesn't have the asyncstate machine overhead. But it's still updating VM properties on a background thread and using a background thread unnecessarily.
此选项具有所有相同的问题,只是它的效率稍高一些,因为它没有async状态机开销。但它仍然在后台线程上更新 VM 属性并不必要地使用后台线程。
public async void loadData()
This one's the worst of all. It inherits the same problems of the others: updating VM properties on a background thread and using an unnecessary background thread. To that it adds the problems of async void. One problem is that NavigationHelper_LoadStatecannot catch any exceptions from loadData. Another problem is that loadDatais not easily testable.
这是最糟糕的。它继承了其他人的相同问题:在后台线程上更新 VM 属性并使用不必要的后台线程。对此,它增加了async void. 一个问题是NavigationHelper_LoadState无法从loadData. 另一个问题是loadData不容易测试。
So just use the simple approach and call it directly:
所以只需使用简单的方法并直接调用它:
await ViewModel.loadData().ConfigureAwait(false);

