Reputation: 45
I am creating an application that requests a small amount of data from a webserver in JSON format, deserializes the data using Json.net, and returns a list of a custom object. I am debugging the application using an android phone.
A listview is then created using the created list. The ui code seems to work with premade objects inserted into the list instead of the async method. The async method crashed the application.
public partial class Membership : ContentPage
{
int increment = 1;
public Membership()
{
//begin task
var task = GetMembers(increment);
//irrelevant stuff happening
//wait for task to complete to continue execution
List<Person> people = task.Result;
// Create the ListView.
ListView listView = new ListView
{
// Source of data items.
ItemsSource = people,
// Define template for displaying each item.
// (Argument of DataTemplate constructor is called for
// each item; it must return a Cell derivative.)
ItemTemplate = new DataTemplate(() =>
{
// Create views with bindings for displaying each property.
Label nameLabel = new Label();
Label statusLabel = new Label();
nameLabel.SetBinding(Label.TextProperty, "name");
statusLabel.SetBinding(Label.TextProperty, "status");
// Return an assembled ViewCell.
return new ViewCell
{
View = new StackLayout
{
Padding = new Thickness(0, 5),
Orientation = StackOrientation.Horizontal,
Children =
{
//boxView,
new StackLayout
{
VerticalOptions = LayoutOptions.Center,
Spacing = 0,
Children =
{
nameLabel,
statusLabel
}
}
}
}
};
})
};
// Build the page.
this.Content = new StackLayout
{
Children =
{
header,
listView
}
};
}
And the async task in question:
async Task<List<Person>> GetMembers(int increment)
{
string jsonString;
using (var client = new HttpClient())
{
//gets the members from the server in json format
//increment defines which set of members (1-50, 51-100, etc)
var responseString = await client.GetStringAsync("GENERIC URL" + "increment=" + increment.ToString());
jsonString = responseString;
}
List<Person> memberList = JsonConvert.DeserializeObject<List<Person>>(jsonString);
return memberList;
}
Now, I've tested this code by bypassing the async task and creating a list of a couple of predefined People, and it worked just fine.
I understand using the task.Result; method will block the application until the async task completes, but, when unit testing there were no problems with speed so I am a bit confused. Any help would be appreciated.
Upvotes: 4
Views: 2812
Reputation: 3979
Because you say:
"No error messages, it just freezes."
In comments, I'm sure you have a deadlock situation here. The Problem with .Result
and .Wait()
is well described in this SO-Ticket:
await works but calling task.Result hangs/deadlocks
Your continuation tries to access a Context which is blocked by .Result
.
You can rebuild your Method like this:
public async Task InitializeMembership()
{
//begin task
var task = GetMembers(increment);
//irrelevant stuff happening
//wait for task to complete to continue execution
List<Person> people = await task;
//Do further stuff
}
As you can see I would use a Method and not the constructor because I think an async constructor isn't best practice. I hope this can solve your issue.
Upvotes: 3