An understanding of ASP. NET asynchronous programming
In this blog post, I want to discuss asynchronous exception operations. However, when I was doing asynchronous testing, I tried ASP again. NET Asynchronization has gained a new understanding. It can be said that my previous understanding of Asynchronization still has some problems. First, let's list three confusing points in this blog post:
-
What is async await ???
-
What should I do if an exception occurs in an asynchronous operation?
-
If an exception occurs in an asynchronous operation, is there a catch throw condition? Will Application_Error be captured?
I have tested asynchronous synchronization in many cases before.) This Time, we write the test code more complicated and then asynchronously. The Code is as follows:
- [Route ("")]
- [HttpGet]
- Public async Task <string> 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 <string> 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 <string> 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 are executed 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 has been executed for countless times, which is roughly the four cases above. I saw the output results at the time, which is actually very messy, and I also share the same results with everyone, I have some questions:Is this really asynchronous programming? Why is the thread so strange? And there is only one thread at the end. What is the difference between this and synchronization ???
I have been thinking about this question for a long time and have some questions about myself: you are writing async await code every day. Do you really know about it ??? Then I found the previous jesse liu blog and read many articles repeatedly. Finally, I finally got some "Epiphany". Combined with the test code above, I drew a rough picture:
Based on the above figure, I will explain my understanding. During the test, HttpClient. getAsync tries its best to keep it running for a long time. For example, the requested URL may be stackoverflow or github. You know why !), Because of the time difference, we can better understand the thread execution. In the figure above, "thread 1, thread 1x, thread 3x, and thread 4x" are not different threads, that is to say, thread 1 may be equal to thread 1x or thread 3x... From the output result, we can see that thread x is used to represent the number of await times between two outputs, which proves a doubt:Await does not necessarily create a thread that is different from the previous one.
What is asynchronous ??? I personally think,Async Asynchronization is a pseudo concept, and await wait is the essenceA thread can respond to multiple requests. For Synchronous Programming, a thread is blocked when processing a request, for example, HttpClient in the above test code. getAsync network operation), then this thread will wait for it to process. During this waiting process, other requests will no longer be able to use this thread, because the number of threads in the IIS thread pool is limited, high concurrency will be a headache in Synchronous Programming. Imagine if the number of threads in the thread pool is 100, when these 100 threads process 100 requests at the same time, they are all sadly congested. At this time, 101st requests cannot be executed, and the concurrency is 100.
What will happen if asynchronous programming is the same processing process? For example, if a thread executes the await operation when processing a request, the thread will be released back to the thread pool and then wait, the original thread can process other requests or other operations of this request. Note that waiting is not waiting for the thread, but waiting for the operation. I didn't understand this place at all, if it is a thread wait, it indicates that this thread will always wait for it to complete. It is the same as Synchronous Programming. Therefore, this understanding is incorrect. You can understand it as follows:There is no thread in the await waiting process !!!
Next, wait for the operation to be completed. At this time, a thread will be randomly taken from the thread pool for execution. The obtained thread may have just been released by the await operation, however, there may also be other threads, and the 2-6 operation in it is like this. A picture is better than a thousand words:
After learning about the entire process, you will understand what the async await is? And what is its real application? Summary:
-
Async Asynchronous Network processing is most effective for HttpClient requests or database connections): We all know this well and understand it well. If it is another operation, for example, if you make a lot of time-consuming calculations in an asynchronous method, this Asynchronous Method will have no effect, to put it bluntly, it is the same as synchronization. For network operations, we generally do not process them. After sending a request, we can wait for it to complete. Therefore, this thread is executed at this time, it can be released and will be transferred to the thread pool. After network operations are completed, a random thread will be taken from the thread pool for further execution.
-
Async Asynchronization is not a true "Asynchronization": What does it mean? You carefully look at the above test output results, will find that the ManagedThreadId1-6 is output in sequence, rather than output ManagedThreadId4 and then output ManagedThreadID3, so asynchronous and synchronous execution process is the same, in addition, the execution time for a request is the same. In a sense, the above asynchronous test shows that nothing can be tested from the test results ),Asynchronization does not reduce the execution time, but increases the number of requests to be executed,This is actually the concurrency.
-
The essence of async Asynchronization is await: As mentioned before,The essence of async Asynchronization is thread recovery during await and thread switching after completion.The biggest value of this operation is to avoid thread waste and wait and make full use of thread execution, which is a bit similar to the landlord's inability to tolerate slaves doing meaningless things, instead, they want to keep working 24 hours a day.
In addition, in ASP. NET applications, we can useThread.CurrentThread
To access the current execution thread, I want to do such a test before, let the current execution thread Sleep for a period of time to see if other threads will execute,Thread.CurrentThread
There is no Sleep method, but you must access it like thisThread.Sleep(int millisecondsTimeout)
If you execute this code in this way, the current thread will Sleep, but other threads will not continue to execute when it Sleep. Why? BecauseThe CPU can only execute one thread within the same period of time.
After learning about what the async await is, the remaining two exceptions related to asynchronous operations at the beginning of blog are easy to understand:
-
What should I do if an exception occurs in an asynchronous operation?: Same as synchronization, errors are reported during synchronization, and errors are also reported asynchronously. Some people may have such questions, such as when the Index Action in the Test code is executed inside the await Test, if an exception is thrown suddenly, I assume that the Index will not be affected since the Test method is asynchronously executed? In fact, you will find that the Index page will throw an exception after execution, soThere is no half-cent relationship between exceptions and Asynchronization..
-
If an exception occurs in an asynchronous operation, is there a catch throw condition? Will Application_Error be captured?: No catch, Application_Error will be captured; if catch is not throw, Application_Error will not be captured; if catch is throw, Application_Error will be captured.
If we want an Asynchronous Method to catch and throw exceptions without affecting other asynchronous methods, for example, our test code:
- [Route ("")]
- [HttpGet]
- Public async Task <string> 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 <string> 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"); // an Exception occurs.
- Return await response. Content. ReadAsStringAsync ();
- }
- }
- Catch (Exception ex)
- {
- System. Diagnostics. Debug. WriteLine ("exception Message:" + ex. Message );
- Return "";
- // Throw ex;
- }
- }
The result is that the Index page will not report errors and will not affect the execution of other methods. Now I find that when I was confused about this problem, I am still an idiot, exceptions and Asynchronization do not have a half-cent relationship. The same problem occurs, as is synchronization.
There are a lot of blog posts. If you don't want to spend time reading them, you can simply remember this article:If your application requests access requests with little concurrency), Asynchronization and synchronization will be the same, and Asynchronization transformation will be meaningless, however, if your application requests access a lot of concurrency), the effect is obvious. If you use Asynchronization, it will save you money on several servers, code Asynchronization does not speed up the execution of your application. code execution speed does not mean any improvement, it is important to write "good code !!!