WPF 应用程序的异步和填充数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21437566/
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 and populating data for WPF application
提问by Killnine
I have a WPF application that initializes the state of the UI via methods in the constructor. However, it's never returning from the Wait();in the constructor.
我有一个 WPF 应用程序,它通过构造函数中的方法初始化 UI 的状态。但是,它永远不会从Wait();构造函数中的返回。
Here's what I am currently doing via a fairly-contrived sample:
这是我目前通过一个相当人为的样本所做的:
public class SomeViewModel
{
public ICommand AddDataCommand { get { return RelayCommand(AddDataExecute); } }
public ObservableCollection<int> UIData { /* Property with INotifyPropertyChanged */}
public SomeViewModel()
{
//Load synch. here
LoadData().Wait();
}
public async Task LoadData()
{
UIData = await Task.Run(() => SomeService.SelectAllUIData());
}
public async void AddDataExecute()
{
//Add new data item to database on separate thread to keep UI responsive
await Task.Run(() => SomeService.AddNewData(0));
//Reload data from database and update UI, has to happen after AddNewData completes
await LoadData();
}
}
I believe it's hanging because I am never actually returning a Task. However, I don't know of a different way to assign UIData asynchronously that works both in the constructor and the Commands that call it.
我相信它挂了,因为我从来没有真正返回Task. 但是,我不知道在构造函数和调用它的命令中都可以使用异步分配 UIData 的不同方法。
回答by Servy
Don't construct the object through a constructor, if you require construction to be asynchronous. Use a static factory method:
如果您要求构造是异步的,请不要通过构造函数构造对象。使用静态工厂方法:
public class SomeViewModel
{
private SomeViewModel()
{ }
public static async Task<SomeViewModel> Create()
{
SomeViewModel model = new SomeViewModel();
await model.LoadData();
return model;
}
public async Task LoadData()
{
UIData = await Task.Run(() => SomeService.SelectAllUIData());
}
//...
}
As for why your code isn't working, you're getting the standard awaitdeadlock in which you're blocking on an asynchronous operation, that blocking is preventing continuations from being called on the UI thread, and with two different operations each waiting on the other to continue, you get a deadlock. This is why it's important to "async all the way up" rather than synchronously blocking on an asynchronous operation.
至于为什么您的代码不起作用,您会遇到标准await死锁,在该死锁中您阻塞了异步操作,该阻塞阻止了在 UI 线程上调用延续,并且有两个不同的操作,每个操作都在等待其他继续,你会陷入僵局。这就是为什么“一直向上异步”而不是同步阻塞异步操作很重要的原因。
回答by Stephen Cleary
You're seeing the classic deadlock situationthat I describe on my blog.
您正在看到我在博客上描述的经典僵局情况。
To solve it, use asyncall the way, as I describe in my MSDN article on asyncbest practices.
要解决它,请使用asyncall way,正如我在关于async最佳实践的MSDN 文章中所述。
This can be difficult in some scenarios. I have a blog post describing a few approaches for asyncconstructors. However, since you're talking about a ViewModel and data for the UI, you'll probably find my blog post on asyncpropertiesmore helpful - in particular, the section on data binding.
这在某些情况下可能很困难。我有一篇博客文章描述了async构造函数的一些方法。但是,由于您在讨论 UI 的 ViewModel 和数据,您可能会发现我关于async属性的博客文章更有帮助 - 特别是关于数据绑定的部分。

