How can I get a row in button_ClickEvent from async method

I guys have the following code:

public static CookieContainer cookies; public static HttpWebRequest GetNewRequest(string targetUrl, CookieContainer SessionCookieContainer) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(targetUrl); request.CookieContainer = SessionCookieContainer; request.AllowAutoRedirect = false; return request; } public async static Task<HttpWebResponse> MakeRequest(HttpWebRequest request, CookieContainer SessionCookieContainer, Dictionary<string, string> parameters = null) { HttpWebResponse response; request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5Accept: */*"; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; request.CookieContainer = SessionCookieContainer; request.AllowAutoRedirect = false; if (parameters != null) { request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; string s = ""; foreach (KeyValuePair<string, string> pair in parameters) { if (s.Length == 0) { s = s + string.Format("{0}={1}", pair.Key, pair.Value); } else { s = s + string.Format("&{0}={1}", pair.Key, pair.Value); } } byte[] bytes = Encoding.UTF8.GetBytes(s); using (Stream stream = await request.GetRequestStreamAsync()) { stream.Write(bytes, 0, bytes.Length); } } request.Method = "GET"; response = await request.GetResponseAsync() as HttpWebResponse; SessionCookieContainer.Add(response.Cookies); while (response.StatusCode == HttpStatusCode.Found) { response.Close(); request = GetNewRequest(response.Headers["Location"], SessionCookieContainer); response = await request.GetResponseAsync() as HttpWebResponse; SessionCookieContainer.Add(response.Cookies); } return response; } 

I use these functions for some method (for example)

 async Task<string> login(string url, string id, string pw) { ///code... } 

My problem: if I want to get the result in buttonclick(object sender, EventArgs e) , how can I do this?

I tried this but did not work:

 private void buttonclick(object sender, EventArgs e) { string htmlPage=login(url, id, pw); } 

EDIT

I solved the problem with adding async between private and void and adding await before login(bla bla)

+2
c # async-await
Nov 07 '13 at
source share
2 answers

While the following obvious solution, it has hidden catches:

 private async void buttonclick(object sender, EventArgs e) { string htmlPage = await login(url, id, pw); } 
  • What if login throws an exception? This will be inconspicuous and most likely will cause the application to crash.
  • What should I do if the user presses the button twice and the previous operation for entering asynchronous mode is already in progress? You, of course, do not want two pending logins.

Here's a slightly improved version:

 Task<string> _pendingLogin = null; private async void buttonclick(object sender, EventArgs e) { if (_pendingLogin != null) { MessageBox.Show("Login pending..."); return; } try { _pendingLogin = login(url, id, pw); string htmlPage = await _pendingLogin; MessageBox.Show("Logged in: " + htmlPage); } catch(Exception ex) { MessageBox.Show("Error in login: " + ex.Message); } _pendingLogin = null; } 
+2
Nov 07 '13 at 23:05
source share

Your login method is Async. Simply put, async methods do not return the result value when called, instead async methods return Task of TResult. A task is a special type, which is a promise to calculate the value of a result. To get the result, you must either:

  • call. The Result property for the Tast object. This will block the caller's flow until the result is calculated. (Very bad for Windows applications, so it makes the application unresponsive and even causes deadlocks (depending on the implementation of the synchronization method).
  • Use the await keyword to wait asynchronously before evaluating the result value. This will allow the calling UI thread to do other things while loading the web page. The user interface thread will return to processing the code after waiting, as soon as the task is completed (the web page is loading). This is preferable for Windows applications, so the application can remain responsive.

Try the following:

 private async void buttonclick(object sender, EventArgs e) { string htmlPage = await login(url, id, pw); } 
+2
Nov 07 '13 at
source share



All Articles