Cool code (asynchronous page in ASP. NET 2.0)

Source: Internet
Author: User
DirectoryAsynchronous pages in ASP. NET 1.x
Asynchronous pages in ASP. NET 2.0
Asynchronous Data Binding
Asynchronously call Web Services
Asynchronous task
Summary

ASP. NET 2.0 provides a variety of new functions, from declarative Data Binding and master pages to membership and role management services. However, I think the coolest new feature is an asynchronous page. Let me tell you why.

When a page request is received, ASP. NET retrieves a thread from a thread pool and assigns the page request to the thread. A common, or synchronous page occupies threads during the request to prevent threads from being used to process other requests. If the synchronous request changes to an I/O intensive state, for example, when the request calls a remote web service or queries a remote database and waits for the call to return, the thread assigned to it is always idle before the call returns. This condition limits scalability because the available threads in the thread pool are limited. If all the threads processing the request are blocked by waiting for the completion of the I/O operation, there will be redundant requests waiting in queue for the release of these threads. The best case is lower throughput, because you need to wait longer to process the request. The worst case is that the queue is filled and ASP. NET cannot process subsequent requests, and the error 503 "server unavailable" is prompted.

The emergence of asynchronous pages provides a concise solution for solving such problems caused by I/O-intensive requests. Page processing is performed on a thread in the thread pool. However, when an asynchronous I/O operation responds to a signal from ASP. NET and starts, the thread returns the original thread pool. After the operation is completed, ASP. NET obtains another thread from the thread pool to process the request. In this way, the thread usage of the thread pool is improved, and the scalability is also enhanced. The threads that are originally blocked by waiting for the completion of the I/O operation can be used to process other requests. The direct advantage of this is to avoid lengthy I/O operations, so you can quickly access the MPs queue. Waiting for a long time to enter the pipeline will have a great negative impact on the execution of such requests.

Currently, there are few articles on the ASP. NET 2.0 Beta 2 asynchronous page infrastructure. To solve this problem, let's take a look at the knowledge of asynchronous pages. Note that this column is based on the beta version of ASP. NET 2.0 and. NET Framework 2.0.

ASP. NET 1.xAsynchronous page in

ASP. NET 1.xAsynchronous pages are not supported, but they can be built with a little patience and imagination. For more information, see Fritz Onion'sMsdnThe magazine's article "using threads in your server-side Web code and building asynchronous handlers ".

The trick is to implement ihttpasynchandler in the Code hiding class of the page so that ASP. NET no longer calls the ihttphandler. processrequest method of the page, but processes various requests by calling ihttpasynchandler. beginprocessrequest. In this way, you can start another thread in the beginprocessrequest implementation section. This thread calls Base. processrequest, so that the page can process requests normally on a non-thread pool thread (such as load events and render events ). At the same time, beginprocessrequest is returned immediately after a new thread is started, so that the thread executing beginprocessrequest can return to the thread pool.

The above is only the basic principle, but the details are far more than that. In addition, you also need to execute iasyncresult and return it in beginprocessrequest. This obviously means creating a manualresetevent object and sending a signal to this object when the background thread returns processrequest. In addition, you need a thread to call base. processrequest. Unfortunately, most traditional technologies that can transfer jobs to backend threads, including thread. start, threadpool. neither queueuserworkitem nor asynchronous delegation can be performed in ASP. net Applications achieve the expected results, because they will either steal threads from the thread pool, or may cause unlimited growth of threads. To correctly implement asynchronous pages, you need to use a custom thread pool. Writing a custom thread pool is not easy. (For more information, see the. NET related question column in The msdn magazine in February 2005.).

Frankly speaking, in ASP. NET 1.xIt is not a fantasy to build an asynchronous page in, but it is very troublesome to do so. After trying this kind of taste, you can't help but desire a better solution. Now we have a solution, that is, ASP. NET 2.0.

Asynchronous pages in ASP. NET 2.0

ASP. NET 2.0 greatly simplifies the process of building asynchronous pages. To start building an asynchronous page, add the following async = "true" attribute to the @ page command of the page:

<%@ Page Async="true" ... %>

 

In essence, this code tells ASP. NET to execute ihttpasynchandler on the page. Next, you need to call the new page. addonprerendercompleteasync method early in the page lifetime (for example, during page_load) to register a begin method and an end method, as shown in the following code:

AddOnPreRenderCompleteAsync (    new BeginEventHandler(MyBeginMethod),    new EndEventHandler (MyEndMethod));

 

Next is the wonderful part. The page continues the normal process until the prerender event is triggered later. ASP. NET calls the begin method previously registered using addonprerendercompleteasync. The begin method starts an asynchronous operation such as database query or web service call and returns immediately. At this time, the thread allocated to the request will also return to the thread pool. In addition, the begin method returns an iasyncresult, which enables ASP. net determine when to complete asynchronous operations, so that ASP. net can extract threads from the thread pool at this time and call the end method. After the end is returned, ASP. NET executes the remaining part of the page lifetime, including the rendering stage. During the period before begin is returned and end is called, the thread processing the request is idle and can provide services for other requests until the end is called and displayed. In addition, because. NET Framework 2.0 provides multiple ways to execute asynchronous operations, you do not even need to execute iasyncresult in most cases. The framework executes it for you.

The Code hiding class in Figure 1 provides an example. The corresponding page contains a label control whose ID is "output ". The page uses the system. net. httpwebrequest class to get content on the http://msdn.microsoft.com. Then it analyzes the returned HTML and writes a list to the label control, listing all the href targets it has found.

Because the HTTP request takes a long time to return, asyncpage. aspx. CS performs asynchronous processing. It registers the begin and end methods in page_load, and CALLS httpwebrequest. begingetresponse in the begin method to start an asynchronous HTTP request. Beginasyncoperation returns iasyncresult returned by begingetresponse to ASP. NET, so that ASP. NET can call endasyncoperation when the HTTP request is complete. Then, endasyncoperation analyzes the content, writes the result to the label control, then presents it, and returns an HTTP Response to the browser.


Figure 2 synchronous page processing and asynchronous page processing

Figure 2 illustrates the differences between synchronous pages and asynchronous pages in ASP. NET 2.0. When a synchronization page is requested, ASP. NET allocates a thread from the thread pool for the request and executes the page on this thread. If the request is paused and an I/O operation is executed in turn, the thread will be occupied until the I/O operation is completed. In this way, the entire lifecycle of the page is complete. In comparison, asynchronous pages are normally executed through the prerender event. Then, the begin method registered using addonprerendercompleteasync will be called, and then the thread used to process the request will return the thread pool. Begin starts an asynchronous I/O operation. After the operation is complete, ASP. NET retrieves another thread from the thread pool and calls the end method to execute the remaining part of the page lifecycle on this thread.


Figure 3 Tracking output shows the asynchronous points of an asynchronous page

The call to begin is the "Asynchronous vertex" of the page ". The trail in Figure 3 shows the exact position of an asynchronous vertex. If you want to call addonprerendercompleteasync, it must be called before the asynchronous point, that is, its call must be no later than the prerender event on the page.

Asynchronous Data Binding

For ASP. NET pages, it is not common to directly use httpwebrequest to request other pages, but it is not uncommon to query databases, and data is usually bound to the results. So how can I use an asynchronous page for asynchronous data binding? The Code hiding class in Figure 4 provides a binding method.

Asyncdatabind. aspx. CS uses the addonprerendercompleteasync mode used by asyncpage. aspx. CS. However, the beginasyncoperation method of asyncdatabind. aspx. CS does not call httpwebrequest. begingetresponse, but calls sqlcommand. beginexecutereader added in ADO. NET 2.0 to execute asynchronous database queries. After the call is complete, endasyncoperation calls sqlcommand. endexecutereader to obtain a sqldatareader, which is then stored in a private field. Sqldatareader is bound to the output gridview control in the event handler of the prerendercomplete event (triggered during the period before the page is rendered after the asynchronous operation is complete. On the surface, the page looks like a normal synchronization page, which uses the gridview to present the database query results. But internally, this page is more scalable because it is not stuck in a thread pool thread waiting for the query to return.

Asynchronously call Web Services

Another I/O-related task that ASP. NET web pages often execute is to call Web Services. Since Web service calls take a long time to return, the pages that execute these calls become an ideal option for asynchronous processing.

Figure 5 shows a method for binding asynchronous pages that call Web Services. This method adopts the same addonprerendercompleteasync mechanism as in Figure 1 and figure 4. The begin method of the page starts an asynchronous web service call by calling the asynchronous begin method of the Web Service proxy. The end method of the page caches a dataset reference returned by the web method in a private field. The prerendercomplete handler binds the dataset to a gridview. The following code displays the web method for this call for your reference:

[WebMethod]public DataSet GetTitles (){    string connect = WebConfigurationManager.ConnectionStrings        ["PubsConnectionString"].ConnectionString;    SqlDataAdapter adapter = new SqlDataAdapter        ("SELECT title_id, title, price FROM titles", connect);    DataSet ds = new DataSet();    adapter.Fill(ds);    return ds;}

 

This is only one method, but not the only one .. Net Framework 2.0 web service proxy supports two asynchronous web service calling mechanisms. One mechanism is. NET Framework 1.x.And 2.0 web service proxy specifically use the begin method and end method in each method. Another mechanism is the new methodasync method and methodcompleted event exclusive to the Web Service proxy of. NET Framework 2.0.

If a web service contains a method named Foo. in addition to methods named Foo, beginfoo, and endfoo, Net Framework 2.0 web service proxy also contains a method named fooasync and an event named foocompleted. You can register a handler for the foocompleted event and call fooasync to asynchronously call Foo, as shown below:

proxy.FooCompleted += new FooCompletedEventHandler (OnFooCompleted);proxy.FooAsync (...);...void OnFooCompleted (Object source, FooCompletedEventArgs e){    // Called when Foo completes}

 

After the asynchronous call started by fooasync is complete, the foocompleted event is triggered to call the foocompleted event handler. The second parameter (foocompletedeventargs) that delegates this event handler (foocompletedeventhandler) and passes it to the handler is generated together with the Web Service proxy. You can access the return value of Foo through foocompletedeventargs. result.

The Code hiding class shown in Figure 6 uses the methodasync mode to asynchronously call the gettitles method of Web Services. In terms of functionality, this page is exactly the same as the page in Figure 5. However, their internal structures are completely different. Asyncwsinvoke2.aspx contains a @ page async = "true" Command similar to asyncwsinvoke1.aspx. However, asyncwsinvoke2.aspx. CS does not call addonprerendercompleteasync, but registers a handler for the gettitlescompleted event and calls gettitlesasync on the Web Service proxy. ASP. NET still delays page rendering until gettitlesasync is complete. In essence, an instance of another newly added class (system. Threading. synchronizationcontext) in version 2.0 is used to receive notifications when asynchronous calls start and complete.

Using methodasync instead of addonprerendercompleteasync to Implement Asynchronous pages has two advantages. 1. methodasync can pass the simulation, culture, and httpcontext. Current to the methodcompleted event handler. Addonprerendercompleteasync cannot do this. Second, if the page can be rendered only after multiple asynchronous calls are completed, you must compile an iasyncresult to use addonprerendercompleteasync, the iasyncresult cannot receive the signal before all calls are completed. The use of methodasync does not require such a large weekly chapter. The ASP. net engine displays the page only after the last call is returned.

Asynchronous task

It is very convenient to use methodasync to make multiple Web Service asynchronous calls on an asynchronous page and present the page only after all the calls are completed. But what if you want to perform multiple asynchronous I/O operations on an asynchronous page and do not want these operations to involve Web Services? Does this mean that you need to re-compile an iasyncresult to return it to ASP. NET to tell ASP. NET when the last call was completed? Fortunately, this is not required.

In ASP. NET 2.0, the system. Web. UI. Page class introduces another method that facilitates asynchronous operations: registerasynctask. Registerasynctask has four advantages over addonprerendercompleteasync. In addition to the begin and end methods, registerasynctask allows you to register a timeout method. If it takes too long to complete an asynchronous operation, you can call this timeout method. You can add an asynctimeout attribute to the @ page command on the page to set timeout in a declarative manner. Asynctimeout = "5" sets the timeout value to 5 seconds. Second, you can call registerasynctask multiple times in a request to register multiple asynchronous operations. When methodasync is used, ASP. NET displays the page only after all operations are completed. Third, you can use the fourth parameter of registerasynctask to pass the status to the begin method. The last advantage is that registerasynctask can pass the simulation, culture, and httpcontext. Current to the end method and timeout method. As described above, the end method registered using addonprerendercompleteasync cannot achieve the same effect.

In other aspects, asynchronous pages relying on registerasynctask are similar to asynchronous pages relying on addonprerendercompleteasync. It still needs to insert an async = "true" attribute in the @ page command (or set the asyncmode attribute of the page to "true" programmatically to achieve the same purpose ), the prerender event is still executed normally. At this time, the begin method registered with registerasynctask is called, and the request is further processed before the last operation is completed. It can be seen that the Code hiding class in Figure 7 is functionally equivalent to the Code hiding class in Figure 1, but the code hiding class in Figure 7 uses registertaskasync instead of addonprerendercompleteasync. Note that when the time used to complete httpwebrequest. begingetrequest is too long, a timeout handler named timeoutasyncoperation is called. The corresponding. aspx file contains an asynctimeout attribute, which sets the timeout interval to 5 seconds. Note that the null value is passed to the fourth parameter of registerasynctask, which was originally used to pass data to the begin method.

Registerasynctask allows an asynchronous page to trigger multiple asynchronous calls and display the page only after all the calls are completed. It also performs well for a single asynchronous call and provides a timeout option not available for addonprerendercompleteasync. If the created asynchronous page only performs one asynchronous call, you can use addonprerendercompleteasync or registerasynctask. However, for asynchronous pages that execute two or more asynchronous calls, registerasynctask can greatly simplify your work.

The timeout value is a page-based setting instead of a call. You may wonder if it is possible to change the timeout value of a single call. In a word, this is impossible. You can programmatically modify the asynctimeout attribute of the page to change the timeout value of each request in sequence, but cannot set different timeout values for different calls of the same request.

Summary

Now you should have an in-depth understanding of the asynchronous pages provided in ASP. NET 2.0. The new ASP.. net. Its architecture allows you to perform multiple asynchronous I/O operations in batches in one request, in addition, you can display the page after all operations are completed. Asynchronous ASP. NET page combined with asynchronous ADO. net and. other asynchronous functions in the. NET Framework provide a powerful and convenient solution to solve the problem of Limited scalability caused by crowded thread pools for I/O-intensive requests.

When constructing an asynchronous page, remember the last point, that is, do not borrow a thread from the thread pool used by ASP. NET to start asynchronous operations. For example, calling threadpool. queueuserworkitem at the asynchronous point of the page is counterproductive because this method will borrow the thread in the thread pool, resulting in no thread available for processing requests. In comparison, calling built-in methods in the framework (such as the httpwebrequest. begingetresponse method and sqlcommand. beginexecutereader method) is usually safe because these methods use the complete port to perform asynchronous operations.

 

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.