The Controller creation Wizard provided by Visual Studio defaults to creating a controller type that inherits from the abstract class controller, so controller can define only the synchronization action method. If we need to define an asynchronous action method, we must inherit the abstract class Asynccontroller. This article asks you to describe two different ways to define asynchronous action and the underlying execution principle.
One, the request processing based on thread pool
Asp. NET processes concurrent HTTP requests through a thread pool mechanism. A Web application maintains a thread pool, and when it detects a request for this application that arrives, it gets an idle thread from the pool to process the request. When the process is finished, the thread is not reclaimed, but is released into the pool again. The thread pool has the maximum capacity of one thread, and if the created thread reaches this limit and all threads are in a "busy" state, the new HTTP request is put into a request queue to wait for a thread that has completed the request Processing task to be released to the pool again.
The threads we use to process HTTP requests are called worker threads, and the county city is naturally called the worker thread pool. Asp. NET this kind of request processing mechanism based on thread pool mainly has the following two advantages:
Reuse of worker threads: Although the cost of creating a thread is not as active as a process, it is not an "overnight" thing, and frequent creation and release of threads can cause significant performance damage. While the thread pool mechanism avoids always creating new worker threads to handle each request, the created worker threads are greatly reused and ultimately improve the throughput of the server.
Limitation of the number of worker threads: the limited resources have a limit on the ability of the server to process requests, or the amount of request concurrency that a server can handle has a critical point, and once this critical point is exceeded, the entire service will crash because it cannot provide enough resources. With a thread pool mechanism with good control over the number of worker threads, the number of requests that ASP.net MVC can handle concurrently is unlikely to exceed the maximum allowable capacity of the thread pool, thus avoiding the unlimited creation of worker threads in high concurrency situations and causing the entire server to crash.
If the request processing operation takes a short time, the worker thread is disposed of in a timely manner to the thread pool for processing the next request. However, for more time-consuming operations, it means that the worker threads will be monopolized by a request for a long time, and if such operations are accessed more frequently, in high concurrency it means that the thread pool may not find idle worker threads to handle the latest arrival requests in a timely manner.
If we were to handle such time-consuming requests asynchronously, the worker thread would allow the background thread to take over and be released into the thread pool in a timely manner for subsequent requests, thereby increasing the throughput of the entire server. It is worth mentioning that asynchronous operations are primarily used for I/O binding operations (such as database access and remote service invocation) rather than CPU-bound operations, because the increase in overall performance of asynchronous operations stems from the fact that when I/O devices are working on a task, the CPU can release it to handle another task. If the time-consuming operation relies primarily on the operation of the native CPU, an asynchronous approach can affect overall performance because of thread scheduling and thread context switching.
Definition of two asynchronous action methods
After understanding the need to define an asynchronous action method in Asynccontroller, let's briefly describe how the asynchronous action method is defined. In general, the asynchronous action method has two definitions, one is to define it as a two-match method Xxxasync/xxxcompleted, and the other is to define a method that returns the type as a task.
xxxasync/xxxcompleted
If we use two matching methods xxxasync/xxxcompleted to define an asynchronous action, we can implement the asynchronous operation in the Xxxasync method and implement the final content rendering in the Xxxcompleted method. Xxxcompleted can be viewed as a callback for Xxxasync, and the Xxxcompleted method is invoked automatically when the operation defined in the Xxxasync method completes asynchronously. Xxxcompleted are defined in a way that is similar to the normal synchronization action method.
As a demo, I defined an asynchronous operation named article in the following homecontroller to render the content of the article with the specified name. We define the asynchronous read of the content of the specified article in the Articleasync method, while the content read in the Articlecompleted method is presented in contentresult form.
1:public class Homecontroller:asynccontroller
2: {
3:public void Articleasync (string name)
4: {
5:asyncmanager.outstandingoperations.increment ();
6:task.factory.startnew (() =>
7: {
8:string path = ControllerContext. HttpContext.Server.MapPath (String. Format (@ "\articles\{0}.html", name));
9:using (StreamReader reader = new StreamReader (path))
: {
11: asyncmanager.parameters["content"] = reader. ReadToEnd ();
12:}
13:asyncmanager.outstandingoperations.decrement ();
14:});
15:}
16:public actionresult articlecompleted (string content)
: {
18:return content (content) ;
19:}
:}
For an asynchronous action method defined in xxxasync/xxxcompleted form, asp.net mvc does not invoke the Xxxasync method asynchronously, so we need to customize the execution of the asynchronous operation in this method. In the Articleasync method defined above, we implement asynchronous reading of the content of the article through parallel programming based on task. When we define an asynchronous action method in xxxasync/xxxcompleted form, we frequently use the Asyncmanager property of controller, which returns a type of Asyncmanager object. We'll talk about it separately in the following section.
In the example provided above, we invoked the increment and decrement methods of the Asyncmanager Outstandingoperations property at the beginning and end of the asynchronous operation to launch a notification for asp.net mvc. In addition, we use the dictionary represented by the Asyncmanager parameters property to hold the arguments passed to the Articlecompleted method. The key (content) in the dictionary matches the parameter name of the articlecompleted, so when the method articlecompleted is invoked, The parameter values specified by the Parameters property of Asyncmanager are automatically used as the corresponding parameter values.