Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling async method on button click

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!

like image 307
Doniyor Niyozov Avatar asked Feb 19 '15 08:02

Doniyor Niyozov


People also ask

How do you call async method in Windows form?

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.

What happens when you call async method?

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.

How do you use await in Blazor?

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.


1 Answers

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); } 
like image 170
Sriram Sakthivel Avatar answered Oct 12 '22 12:10

Sriram Sakthivel