I created Windows Phone 8.1 project and I am trying to run async method GetResponse(string url) on button click and waiting for the method to finish, but method is never finishing. Here is my code:
private void Button_Click(object sender, RoutedEventArgs
{
Task<List<MyObject>> task = GetResponse<MyObject>("my url");
task.Wait();
var items = task.Result; //break point here
}
public static async Task<List<T>> GetResponse<T>(string url)
{
List<T> items = null;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
var response = (HttpWebResponse)await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
try
{
Stream stream = response.GetResponseStream();
StreamReader strReader = new StreamReader(stream);
string text = strReader.ReadToEnd();
items = JsonConvert.DeserializeObject<List<T>>(text);
}
catch (WebException)
{
throw;
}
return items;
}
It will hang on task.Wait().
I changed my button click method to async and used await before the async method and I get the result(await GetResponse<string>("url")
). What is wrong with Task<List<string>> task = GetResponse<string>("url")
?
What am I doing wrong?
Thanks for the help!
You're the victim of the classic deadlock.
task.Wait()
ortask.Result
is a blocking call in UI thread which causes the deadlock.Don't block in the UI thread. Never do it. Just await it.
Btw, why are you catching the
WebException
and throwing it back? It would be better if you simply don't catch it. Both are same.Also I can see you're mixing the asynchronous code with synchronous code inside the
GetResponse
method.StreamReader.ReadToEnd
is a blocking call --you should be usingStreamReader.ReadToEndAsync
.Also use "Async" suffix to methods which returns a Task or asynchronous to follow the TAP("Task based Asynchronous Pattern") convention as Jon says.
Your method should look something like the following when you've addressed all the above concerns.
This is what's killing you:
That's blocking the UI thread until the task has completed - but the task is an async method which is going to try to get back to the UI thread after it "pauses" and awaits an async result. It can't do that, because you're blocking the UI thread...
There's nothing in your code which really looks like it needs to be on the UI thread anyway, but assuming you really do want it there, you should use:
Or just:
Now instead of blocking until the task has completed, the
Button_Click
method will return after scheduling a continuation to fire when the task has completed. (That's how async/await works, basically.)Note that I would also rename
GetResponse
toGetResponseAsync
for clarity.use below code