Communication between thread deadlocks of async and await in ASP. NET [MVC]-synchronizationcontext

Source: Internet
Author: User

I have heard that there is a good friend async and await in. net4.5. I can't wait to take it. Nima is a tragedy.

Scenario Reconstruction

 1 public ActionResult Index(string ucode) 2 { 3     string userInfo = GetUserInfo(ucode).Result; 4     ViewData["UserInfo"] = userInfo; 5     return View(); 6 } 7  8 async Task<string> GetUserInfo(string ucode) 9 {10     HttpClient client = new HttpClient();11     var httpContent = new FormUrlEncodedContent(new Dictionary<string, string>()12     {13         {"ucode", ucode}14     });15     string uri = "http://www.xxxx.com/user/get";16     var response = await client.PostAsync(uri, httpContent);17     return response.Content.ReadAsStringAsync().Result;18 }

The above Code simplifies real cases, that is, it is very easy to obtain user information through a third-party openapi and then display it on the index page. After I clicked it, I found that VaR response = await client. postasync (Uri, httpcontent) was executed; the yellow arrow disappeared after entering the code. I waited for half a night, and then ...... Then there will be no more, no exception, only loneliness.

I first considered whether it was caused by httpclient (previously using httpwebrequest. getresponse could be executed as expected, so it would not be a response). I checked a lot of information and made repeated modifications to the code. The problem persists. Later, I changed the last two lines:

1 var response = client.PostAsync(uri, httpContent).Result.Content.ReadAsStringAsync().Result;2 return response;

The problem suddenly disappears. When the index page is displayed in front of me, I say this is not a play for me. I comforted myself that this may be an unknown bug in the. NET Framework. I am unlucky to encounter it. Don't worry about it. After one night of hard work, I quickly fell asleep. Dream test in English, the exam can only see the dense a, I was sweating, and then take a closer look, full of two words: async and await. I woke up.

Async and await

Async and await Are simplified syntax for asynchronous programming. Speaking of Asynchronization, it involves the thread and logic execution sequence. The following code is clear.

1 class Program 2 {3 static void main (string [] ARGs) 4 {5 console. writeline ("Step1, thread ID: {0}", system. threading. thread. currentthread. managedthreadid); 6 7 asyncdemo demo = new asyncdemo (); 8 // demo. asyncsleep (). wait (); // wait will block the current thread until asyncsleep returns 9 demo. asyncsleep (); // The current thread 10 11 console will not be blocked. writeline ("step5, thread ID: {0}", system. threading. thread. currentthread. managedthreadid); 12 console. readline (); 13} 14} 15 16 public class asyncdemo17 {18 19 public async task asyncsleep () 20 {21 console. writeline ("step2, thread ID: {0}", system. threading. thread. currentthread. managedthreadid); 22 23 // await keyword indicates waiting for task. after the logic passed in by run is executed, the call of asyncsleep can continue to run 24 // task. run will open up a new thread to execute the specified logic 25 await task. run () => sleep (10); 26 27 console. writeline ("step4, thread ID: {0}", system. threading. thread. currentthread. managedthreadid); 28} 29 30 private void sleep (INT second) 31 {32 console. writeline ("Step3, thread ID: {0}", system. threading. thread. currentthread. managedthreadid); 33 34 thread. sleep (secondd * 1000); 35} 36 37}

Running results: Although step2 and step4 are in the same method, their running threads are different. step4 and Step3 use the new thread opened by task. Run. NOTE: If we use task. run again in sleep and open up a new thread, assuming that the ID is 10 and modified by the await keyword, step 4 will run in thread 10. Assume that the comments of lines 8th and 9 are exchanged:

1 demo. asyncsleep (). Wait (); // wait will block the current thread until asyncsleep returns 2 // demo. asyncsleep (); // It will not block the current thread

That is to say, the asynchronous logic synchronous return is controlled by humans. In fact, this is the same scenario as the previous user information retrieval scenario. It is assumed that no subsequent output is provided after Step 2 or step 3 is executed. Running result: it seems "counterproductive ". So what happened to the previous problem? Since step4 and Step1 are different threads, what can we think? Of course the thread is deadlocked!

Question: change row 25th to task. Run () => sleep (10). Wait (). What will be output at this time, or what is the output thread ID of Step 4? Task. Wait (); unlike await, it blocks the current thread (regardless of whether the internal logic opens up a new thread ). Running result: You can see that step 4 is still running in the main thread.

Thread deadlock

There are many causes of thread deadlocks. In the ASP. NET [MVC] scenario, a concept involved isAspnetsynchronizationcontextIt can only be exclusive by one thread at the same time. Combined with the features of async and await, return to the code at the beginning of this article:

1 Public actionresult index (string ucode) 2 {3 string userinfo = getuserinfo (ucode). Result; // thread a is blocked and waits for getuserinfo to return. The current contextAspnetsynchronizationcontext4 viewdata ["userinfo"] = userinfo; 5 return view (); 6} 7 8 async task <string> getuserinfo (string ucode) 9 {10 httpclient client = new httpclient (); 11 var httpcontent = new formurlencodedcontent (new dictionary <string, string> () 12 {13 {"ucode ", ucode} 14}); 15 string uri = "http://www.xxxx.com/user/get"; // client. postasync opens a new thread (set to B) in it for asynchronous execution. Note that await does not block the current thread, but will control the caller of the returned method. Here is index action16 var respons. E = await client. postasync (Uri, httpcontent); // client. postasync returns, but the following code is still running in thread B. Current Method attempts to reimportAspnetsynchronizationcontext. the deadlock is generated here.17 return response. content. readasstringasync (). Result; 18}

Solution:

  1. VaR response = await client. postasync (Uri, httpcontent). configureawait (false); // 16th rows
  2. Used by the callerAwait calls the async Method, RatherGetResult、Task.Resul、TAsk. Wait; // 3rd rows
  3. Use client. postasync (Uri, httpcontent). Result. content. readasstringasync (). result. // Block the current thread rather than returning control to the caller, as described above

References

  • Asynchronous programming with async and await (C # and Visual Basic)
  • Httpclient, httpclienthandler, and webrequesthandler explained
  • Httpclient. getasync (...) Never returns when using await/async
  • Synchronizationcontext Overview
  • Communication between threads --- synchronizationcontext

Reprinted please indicate the source of this article: http://www.cnblogs.com/newton/archive/2013/05/13/3075039.html

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.