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.
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.
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 await
deadlock 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.
You're seeing the classic deadlock situation that I describe on my blog.
To solve it, use async
all the way, as I describe in my MSDN article on async
best practices.
This can be difficult in some scenarios. I have a blog post describing a few approaches for async
constructors. However, since you're talking about a ViewModel and data for the UI, you'll probably find my blog post on async
properties more helpful - in particular, the section on data binding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With