Summary: I would like to call an asynchronous method in a constructor. Is this possible?
Details: I have a method called getwritings()
that parses JSON data. Everything works fine if I just call getwritings()
in an async
method and put await
to left of it. However , when I create a LongListView
in my page and try to populate it I'm finding that getWritings()
is surprisingly returning null
and the LongListView
is empty.
To address this problem, I tried changing the return type of getWritings()
to Task<List<Writing>>
and then retrieving the result in the constructor via getWritings().Result
. However, doing that ends up blocking the UI thread.
public partial class Page2 : PhoneApplicationPage
{
List<Writing> writings;
public Page2()
{
InitializeComponent();
getWritings();
}
private async void getWritings()
{
string jsonData = await JsonDataManager.GetJsonAsync("1");
JObject obj = JObject.Parse(jsonData);
JArray array = (JArray)obj["posts"];
for (int i = 0; i < array.Count; i++)
{
Writing writing = new Writing();
writing.content = JsonDataManager.JsonParse(array, i, "content");
writing.date = JsonDataManager.JsonParse(array, i, "date");
writing.image = JsonDataManager.JsonParse(array, i, "url");
writing.summary = JsonDataManager.JsonParse(array, i, "excerpt");
writing.title = JsonDataManager.JsonParse(array, i, "title");
writings.Add(writing);
}
myLongList.ItemsSource = writings;
}
}
The best solution is to acknowledge the asynchronous nature of the download and design for it.
In other words, decide what your application should look like while the data is downloading. Have the page constructor set up that view, and start the download. When the download completes update the page to display the data.
I have a blog post on asynchronous constructors that you may find useful. Also, some MSDN articles; one on asynchronous data-binding (if you're using MVVM) and another on asynchronous best practices (i.e., you should avoid async void
).