I created Windows Phone 8.1 project and I am trying to run async
method GetResponse<T>(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!
Each delegate provides a BeginInvoke() and EndInvoke() method. To invoke a method asynchronously, wrap it in a delegate and call BeginInvoke() on the delegate. The delegate will delegate the act of invoking the method to a thread from the thread pool, thus making it asynchronous towards the caller.
The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.
Await {UIEvent code as Task}; Invoke(StateHasChanged); In example one and two, look at what OnClick is returning - a void . The event loaded on the SynchronisationContext has nothing to wait on. In the first codeblock, the code is all synchronous so runs to completion before the UI update.
You're the victim of the classic deadlock. task.Wait()
or task.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.
private async void Button_Click(object sender, RoutedEventArgs { var task = GetResponseAsync<MyObject>("my url"); var items = await task; }
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 using StreamReader.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.
public static async Task<List<T>> GetResponseAsync<T>(string url) { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); var response = (HttpWebResponse)await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null); Stream stream = response.GetResponseStream(); StreamReader strReader = new StreamReader(stream); string text = await strReader.ReadToEndAsync(); return JsonConvert.DeserializeObject<List<T>>(text); }
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