wpf MVVM XAML 应用程序中的异步等待
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28411306/
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
Async await in MVVM XAML Applications
提问by MistyK
I try to understand how should I receive initial data in my ViewModels with async/await pattern. Let's look at the code:
我试图了解我应该如何使用 async/await 模式在我的 ViewModel 中接收初始数据。让我们看一下代码:
public interface IPeopleService
{
Task<IEnumerable<Person> GetPeopleAsync();
}
public MainViewModel
{
public ObservableCollection<Person> People{get;set;}
public MainViewModel(IPeopleService peopleService)
{
LoadMyData(peopleService);
}
public async Task LoadMyData(IPeopleService peopleService)
{
try
{
People = await peopleService.GetPeopleAsync();
}
catch(Exception e)
{
//log
//notify user
}
}
}
There is a PeopleService which contains asynchronous method to People Data. It is injected with IOC (whatever). After that I invoke asynchronous operation LoadMyData (to prevent blocking UI, so no await keyword) and inside that method I invoke asynchronous operation from service catching all exceptions and notyfying user. What's wrong with this approach?
有一个 PeopleService,其中包含人员数据的异步方法。它注入了 IOC(无论如何)。之后,我调用异步操作 LoadMyData(以防止阻塞 UI,因此没有 await 关键字)并在该方法中调用异步操作从服务捕获所有异常并通知用户。这种方法有什么问题?
I read article from msdn: https://msdn.microsoft.com/en-us/magazine/dn605875.aspxand when I noticed creating a generic class for this kind of Tasks and changing all my properties to use that class as generic parameter, change XAML Bindings to receive a Property.Result property, I think it's crazy and creates a big mess in the project. Furthermore properties in ViewModel specifies that this property is asynchronous which in my opinion is bad design. What is the EASIEST way to solve my problem? Is my solution acceptable to keep everything simple?
我从 msdn 阅读文章:https: //msdn.microsoft.com/en-us/magazine/dn605875.aspx并且当我注意到为此类任务创建通用类并更改我的所有属性以使用该类作为通用参数时, 更改 XAML Bindings 以接收 Property.Result 属性,我认为这很疯狂并且在项目中造成了很大的混乱。此外,ViewModel 中的属性指定此属性是异步的,在我看来这是糟糕的设计。解决我的问题最简单的方法是什么?我的解决方案可以让一切变得简单吗?
回答by Stephen Cleary
After that I invoke asynchronous operation LoadMyData (to prevent blocking UI, so no await keyword) and inside that method I invoke asynchronous operation from service catching all exceptions and notyfying user. What's wrong with this approach?
之后,我调用异步操作 LoadMyData(以防止阻塞 UI,因此没有 await 关键字)并在该方法中调用异步操作从服务捕获所有异常并通知用户。这种方法有什么问题?
Your UI is not blocked while loading the data. That's good. But asynchronous data loading brings up some questions: What does the UI show while the data is loading? How does the UI show errors to the user?
加载数据时您的 UI 不会被阻止。那挺好的。但是异步数据加载带来了一些问题:加载数据时 UI 显示什么?UI 如何向用户显示错误?
In your current code, the UI list is just empty while the data is loading. IMO there should be at the very least a "loading" kind of state so the user can distinguish between an empty result set and an operation still in progress. Also, your notify usercode I assume is bringing up a dialog box or something - via code, not via data binding. IMO an error indicator is better than a modal dialog.
在您当前的代码中,加载数据时 UI 列表是空的。IMO 至少应该有一种“加载”状态,以便用户可以区分空结果集和仍在进行中的操作。另外,notify user我假设您的代码是通过代码而不是数据绑定来打开对话框或其他东西。IMO 错误指示器比模态对话框更好。
The purpose behind NotifyTaskCompletion<T>is that it acts as a data-bindable asynchronous operation. So you can use its properties to change to/from the "loading" and "error" states. This is why your bindings have to change to .Result- because you're binding to the resultof the asynchronous operation. If you don't want to display a "loading" indicator and you don't want to display errors via data-binding, then yes, NotifyTaskCompletion<T>would be overkill.
背后的目的NotifyTaskCompletion<T>是它充当可绑定数据的异步操作。所以你可以使用它的属性来改变“加载”和“错误”状态。这就是为什么您的绑定必须更改为.Result- 因为您绑定到异步操作的结果。如果您不想显示“正在加载”指示器并且不想通过数据绑定显示错误,那么是的,NotifyTaskCompletion<T>就有点矫枉过正了。
It depends on how much you want to do data-binding. If you're happy with it all being in code, then that's fine:
这取决于您想要进行多少数据绑定。如果您对代码中的所有内容感到满意,那很好:
public async Task LoadMyData(IPeopleService peopleService)
{
try
{
... // Hide people display
... // Show loading indicator
People = await peopleService.GetPeopleAsync();
... // Show people display
}
catch(Exception e)
{
... // Show error indicator
}
finally
{
... // Hide loading indicator
}
}
Or, you can do it all with data binding, which makes your code simpler:
或者,您可以使用数据绑定来完成这一切,这使您的代码更简单:
// (wrapped in NotifyTaskCompletion)
public async Task LoadMyData(IPeopleService peopleService)
{
People = await peopleService.GetPeopleAsync();
}
I've done it both ways, but I lean towards NotifyTaskCompletion<T>if I have a project that does a lot of asynchronous operations.
我两种方式都做过,但我倾向于NotifyTaskCompletion<T>是否有一个执行大量异步操作的项目。

