Originally this blog would like to explore the abnormal operation in the asynchronous, but in doing asynchronous testing, but also to ASP.net asynchronous have a new understanding, you can say that their understanding of the asynchronous or some of the problems, first of all, this blog three points:
What the hell is async await???
An exception occurred in an asynchronous operation, how do I handle it?
An exception occurred in an asynchronous operation (whether there is a catch throw condition), Application_Error will not capture?
Previously tested for synchronization in Asynchrony (in many cases), this time we wrote the test Code more complex (asynchronously), and the code was as follows:
- [Route ("")]
- [HttpGet]
- Public async task Index ()
- {
- System.Diagnostics.Debug.WriteLine ("THREAD.CURRENTTHREAD.MANAGEDTHREADID1:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- var result = await Test ();
- System.Diagnostics.Debug.WriteLine ("Thread.CurrentThread.ManagedThreadId6:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- return result;
- }
- public static async task Test ()
- {
- System.Diagnostics.Debug.WriteLine ("THREAD.CURRENTTHREAD.MANAGEDTHREADID2:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- using (var client = new HttpClient ())
- {
- var response = await client. Getasync ("http://stackoverflow.com/questions/14996529/ Why-is-my-async-asp-net-web-api-controller-blocking-the-main-thread ");
- await Test2 ();
- System.Diagnostics.Debug.WriteLine ("THREAD.CURRENTTHREAD.MANAGEDTHREADID5:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- return await response. Content.readasstringasync ();
- }
- }
- public static async task Test2 ()
- {
- System.Diagnostics.Debug.WriteLine ("THREAD.CURRENTTHREAD.MANAGEDTHREADID3:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- using (var client = new HttpClient ())
- {
- var response = await client. Getasync ("Http://stackoverflow.com/questions/33408905/pgadminiii-bug-on-query-tool");
- System.Diagnostics.Debug.WriteLine ("Thread.CurrentThread.ManagedThreadId4:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- return await response. Content.readasstringasync ();
- }
- }
- Output results (performed four times):
- Thread.currentthread.managedthreadid1:8
- Thread.currentthread.managedthreadid2:8
- Thread.currentthread.managedthreadid3:6
- Thread.currentthread.managedthreadid4:6
- Thread.currentthread.managedthreadid5:6
- Thread.currentthread.managedthreadid6:6
- Thread.currentthread.managedthreadid1:7
- Thread.currentthread.managedthreadid2:7
- Thread.currentthread.managedthreadid3:8
- Thread.currentthread.managedthreadid4:7
- Thread.currentthread.managedthreadid5:7
- Thread.currentthread.managedthreadid6:7
- Thread.currentthread.managedthreadid1:5
- Thread.currentthread.managedthreadid2:5
- Thread.currentthread.managedthreadid3:5
- Thread.currentthread.managedthreadid4:6
- Thread.currentthread.managedthreadid5:6
- Thread.currentthread.managedthreadid6:6
- Thread.currentthread.managedthreadid1:8
- Thread.currentthread.managedthreadid2:8
- Thread.currentthread.managedthreadid3:8
- Thread.currentthread.managedthreadid4:8
- Thread.currentthread.managedthreadid5:8
- Thread.currentthread.managedthreadid6:8
This test method, I performed countless times, roughly the above four kinds of situation, I saw the output, in fact, is very messy, I also have the same, and there are some doubts: You This is really asynchronous programming? Why are threads so strange? And the last one has only one thread, what's the difference between this and synchronization???
In response to this question, I thought for a long time, and I have some doubts about the voice: you are writing async await code every day, do you really understand it??? Then I went back to the top of Jesse Liu's blog, repeatedly read a lot of articles, and finally have some "epiphany", combined with the test code above, I drew a sketch map:
Combined with the above diagram, I said my own understanding, in the test, httpclient.getasync as far as possible to allow it to perform longer, such as the request URL can be StackOverflow or github (reason you understand!) Because there is a time lag, so we can better understand the execution of the thread, the figure above "Thread 1, thread 1x, thread 3x, thread 4x", and so on, these are not different threads, that is, thread 1 may be equal to thread 1x or thread 3x ... From the output above, we can see that using thread X to represent the number of await experienced between two outputs proves a puzzle:await does not necessarily create a thread that is not the same as before.
What exactly is asynchronous??? I personally feel thatasync asynchronous is a pseudo concept, await wait is the essence of a thread can respond to multiple requests, if it is synchronous programming, a thread in the processing of a request when the blocking (such as the above test code in the Httpclient.getasync Network operation), then this thread will wait for it to process, in this waiting process, then other requests can no longer use this thread, and because the number of threads in the IIS thread pool is limited, then synchronous programming, high concurrency will be a headache, imagine, if the thread pool in the number of threads is 100, When these 100 threads handle 100 requests at the same time, they are both sad and blocking, and the 101th request will not execute, then the concurrency amount is 100.
Then, the same process, if it is asynchronous programming, what will be the case? For example, when a thread is processing a request, execute to the await operation, then this thread will be released back to the thread pool, then wait, the original thread can handle other requests or other operations of this request, note that waiting is not a thread waiting, but an operation waiting, I did not understand this place, if it is a thread waiting, it means that this thread will always wait for it to complete, and synchronous programming is the same, so this understanding is wrong, you can understand:await waiting in the process, there is no thread!!!
And then up there, after waiting for the operation completes, this time will take a thread from the thread pool randomly to carry on execution, the obtained thread may be the await operation just released, but also may be other threads, the above figure 2-6 operation is like this, a picture wins thousand words:
Understand the whole process, you will understand async await what kind of ghost? And what does it really have to do with it? A brief summary of a few things:
-
Async Asynchronous Network processing is most obvious (HttpClient request or database connection) : This is very clear to all of us, and it is well understood that if it is something else, such as an asynchronous method, you do a lot of time-consuming calculations, That this asynchronous will have no effect, as plainly as sync, and for network operations, we generally do not do processing, to initiate a request to wait for it to complete the line, so this time to execute the thread, can be released and will go to the thread pool, the network operation completed, and then randomly take a thread from the thread pool to continue execution.
-
Async Asynchronous is not really an "asynchronous" : What does that mean? If you look carefully at the output of the test above, you will find that the managedthreadid1-6 is sequentially output, rather than outputting the ManagedThreadId4 and then outputting the ManagedThreadID3, so the asynchronous and synchronous execution is the same, and a request , and the execution time is the same, the above asynchronous test in some sense, is not testing anything (from the test results can be seen), asynchronous does not reduce your execution time, but increase the number of requests to execute, this thing, in fact, is the concurrent volume. The essence of the
-
Async Asynchronous is await : This has been mentioned before, and to be exact, the essence of the async asynchronous is that the thread is recycled when await and the thread switch after completion , the greatest value of this operation is to avoid the waste of threads waiting, to take full advantage of the execution of threads, a bit like the landlord can not tolerate slaves idle to do meaningless things, but want them to work 24 hours non-stop.
In addition, in the ASP.net application, we can use Thread.CurrentThread
to access the current execution thread, and I wanted to do a test that would allow the current thread to sleep for a while to see if other threads would execute, but Thread.CurrentThread
not the sleep method, which had to be accessed Thread.Sleep(int millisecondsTimeout)
, If this code is executed like this, then when the thread is going to sleep, but the other threads do not go on while it is sleep, why? Because the CPU can only execute one thread during the same time period.
When I learned what async await was, the first two remaining questions about the exception in asynchronous operations are now easy to understand:
An exception occurred in an asynchronous operation, how do I handle it? : and synchronous processing, the synchronization of the error, asynchronous also the same error, some people may have such a question, such as the test code in the Index action, execution to await test internal operations, suddenly throw an exception, and then take it for granted that, since it is asynchronous execution of test method, the Index should not affect it? In fact, you will find that the Index page will still throw an exception, so abnormal and asynchronous not half a dime relationship .
An exception occurred in an asynchronous operation (whether there is a catch throw condition), Application_Error will not capture? : No catch,application_error will be captured, there will be catch no throw,application_error will not be caught, there are catch and throw,application_error can catch.
If we want to have an asynchronous method that throws an exception without affecting other asynchronous methods, we catch it without throw, such as our test code:
- [Route ("")]
- [HttpGet]
- Public async task Index ()
- {
- System.Diagnostics.Debug.WriteLine ("THREAD.CURRENTTHREAD.MANAGEDTHREADID1:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- var result = await Test ();
- System.Diagnostics.Debug.WriteLine ("Thread.CurrentThread.ManagedThreadId6:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- return result;
- }
- public static async task Test ()
- {
- Try
- {
- System.Diagnostics.Debug.WriteLine ("THREAD.CURRENTTHREAD.MANAGEDTHREADID2:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- using (var client = new HttpClient ())
- {
- var response = await client. Getasync ("Http://stackoverflow.com/questions/33408905/pgadminiii-bug-on-query-tool");
- System.Diagnostics.Debug.WriteLine ("THREAD.CURRENTTHREAD.MANAGEDTHREADID3:" + THREAD.CURRENTTHREAD.MANAGEDTHREADID);
- throw new Exception ("Test Exception");//There's an exception here.
- return await response. Content.readasstringasync ();
- }
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine ("Exception info:" + ex.) message);
- Return "";
- Throw ex;
- }
- }
The effect is that the Index page will not be an error, and will not affect the implementation of other methods, and now found that the question at that time, but also pretty stupid, or that sentence, abnormal and asynchronous not half a dime of the relationship, the same problem, synchronization is to deal with this.
There's a lot of content in the blog, if you don't want to spend time looking, you can remember this phrase directly: If your application requests very little access (concurrency is very small), asynchronous and synchronous will be the same effect, asynchronous transformation is meaningless, and if your application request access to a lot (concurrency is very large), then the effect is obvious, If you use Asynchrony, you'll save money for a few servers, but code asynchrony does not make your application faster (meaning code execution speed), spam or spam, and there's no improvement, so it's important to write good code!!!