Multithreading in Web development can enhance user experience, especially when multiple users, multitasking, massive data, and resources are insufficient. So ourASP. NET tutorialSet upSpecial topics on multi-thread programming. The followingCodeThe examples are all entry-level, hoping to help you learn ASP. NET multi-threaded programming.
ASP. NET tutorial series: multi-threaded programming practice 2 examples of using multi-threaded ASP. NET
Multithreading is used to improve CPU utilization, that is, to do more things in the same time (but the premise is that the system resources are not completely exhausted), Asp. using multithreading in. Net can speed up page generation on the server. Generally, the most time-consuming page generation process is the database query stage. If you have 10 queries on the page and do not use multithreading, these 10 queries will be executed serially-that is, each query is executed sequentially. If multithreading is used, these 10 queries can be executed almost simultaneously. This will obviously increase the page generation speed.
I searched some posts on the Internet and said that multithreading is unstable in the IIS process. However, I have found that ASP. NET does not have any problems with multithreading. However, you must pay attention to the use of multithreading in ASP. NET. Otherwise, it is indeed unstable or even unfeasible. For example, you cannot use any methods or attributes in httpcontext in multiple threads, including cookie, session, response, request, and application. When using these methods or attributes, the IIS process will crash. Note that because multi‑thread and page load are executed asynchronously, the created threads must be synchronized before the load is executed. Otherwise, data may not be loaded successfully. Some may ask if httpcontext and so on are all restricted. What else can be done on the page? We can completely separate the created thread from the page body, and obtain the required data in the page body first, and then directly import the data to the created thread. For more information, see the following.
Assume that there are two SQL queries in a page. One is to determine the content of the current page based on the parameter P passed by the URL, and the other is to display all categories. The first query statement uses request. querystring to obtain the page number transmitted by P. The second query statement can directly write an SQL statement.
Assume that the first query statement is: Select * from archives where page = the passed page number.
Assume that the second query statement is select * from category.
First, we create a class to accept the p parameter and the data binding control ID (Here we use the Repeater control to bind data). This class can bind the SQL statement query result to the Data Control (repeater).
Public classbinddata
{
Private int currentpage = 1;
Private repeater rpid;
Public binddata (repeater rpid)
{
This. rpid = rpid;
}
Public binddata (repeater rpid, int page)
{
This. rpid = rpid;
This. currentpage = page;
}
Public void bindcategory ()
{
String strsql = "select * from category ";
This. binddatatorepeater (strsql, this. rpid );
}
Public void bindarchive ()
{
String strsql = string. Format ("select * from archives where page = {0}", this. currentpage );
This. binddatatorepeater (strsql, this. rpid );
}
Private void binddatatorepeater (string strsql, repeater RP)
{
If (Rp = NULL) return;
Sqlconnection conn = new sqlconnection ("Data Source = data server address; user id = user name; Pwd = password; initial catalog = database name ");
Sqlcommand cmd = new sqlcommand (strsql, Conn );
Sqldatareader DTR;
Try
{
Conn. open ();
DTR = cmd. executereader ();
Controlid. datasource = RP;
Controlid. databind ();
If (! DTR. isclosed)
DTR. Close ();
}
Catch {}
Finally
{
Cmd. Dispose ();
If (conn. State = connectionstate. open)
Conn. Close ();
}
}
}
The binddata class created above has two constructors, which are used to bind a category and bind arhive in different forms. If other data binding controls are used, you can modify them accordingly;
A private method binddatatorepeater is created to bind the query result of the corresponding SQL statement to the corresponding Repeater control. Sqldatareader is used in this method to increase the data binding speed. If you use the data factory, you can modify the specific implementation process in binddatatorepeater;
The two common methods bindcategory and bindarchive are used to create different SQL statements and set the repater ID;
At the same time, we need to introduce three necessary namespaces: system. Web. UI. htmlcontrols, and system. Data. sqlclient.
It is worth noting that try is used in the binddatatorepeater method .. catch statement, but does not do anything in the Catch Block. Why do we use try. catch does not do anything in the Catch Block. Isn't it an extra move? Use try .. catch is used to prevent the execution of binddatatorepeater from throwing an exception. If an exception occurs and this method is executed in multiple threads, it will cause the IIS process to crash and affect the normal execution of other pages, so try... catch prevents binddatatorepeater from throwing an error.
We create a class for Data Binding to improve memory utilization. When the data load is completed, the instances created for this class will be destroyed. You can also create several global variables on the page. However, we recommend that you pass data in the form of a class instead of using global variables. Next, we start to create a thread in the load of the page. First, you need to introduce the system. Threading namespace in the page.
Public classbinddata
{
Private int currentpage = 1;
Private repeater rpid;
Public binddata (repeater rpid)
{
This. rpid = rpid;
}
Public binddata (repeater rpid, int page)
{
This. rpid = rpid;
This. currentpage = page;
}
Public void bindcategory ()
{
String strsql = "select * from category ";
This. binddatatorepeater (strsql, this. rpid );
}
Public void bindarchive ()
{
String strsql = string. Format ("select * from archives where page = {0}", this. currentpage );
This. binddatatorepeater (strsql, this. rpid );
}
Private void binddatatorepeater (string strsql, repeater RP)
{
If (Rp = NULL) return;
Sqlconnection conn = new sqlconnection ("Data Source = data server address; user id = user name; Pwd = password; initial catalog = database name ");
Sqlcommand cmd = new sqlcommand (strsql, Conn );
Sqldatareader DTR;
Try
{
Conn. open ();
DTR = cmd. executereader ();
Controlid. datasource = RP;
Controlid. databind ();
If (! DTR. isclosed)
DTR. Close ();
}
Catch {}
Finally
{
Cmd. Dispose ();
If (conn. State = connectionstate. open)
Conn. Close ();
}
}
}
The above code is displayed in! Bind data in the ispostback status. Use request. querystring obtains the current page number, creates two binddata instances loadarchives and loadcategory, and uses thread tharhives = new thread (New threadstart (loadarchives. bindarchive) creates a thread for BIND arhice by Using thread thcategory = new thread (New threadstart (loadcategory. bindcategory) creates a thread for the BIND category, and calls the start method of the thread to bring the two threads into the execution status. Finally, use the thread join method at the bottom of load to synchronize the two created threads with page loading.
It is worth noting that the join method is required. If it is not used, the created thread may not have fully bound the data to the repeater, and the load has been executed, if so, there will be no data on the page. At the same time, the Code lines that call start should be as early as possible, and the code lines that call join should be as late as possible-put them at the end of the page_load code segment as far as possible to achieve the goal of multithreading, if you call a start operation to call join immediately, the actual performance is the same as that without multithreading. The explanation of join on msnd is that the calling thread is blocked until a thread is terminated while the standard COM and sendmessage message pump processing continues.
You only need to set the repeater binding item on the ASPX page, and the data can be loaded successfully. The preceding shows only two SQL statement queries. If you have 10 or more SQL queries, create 10 threads in page_load for asynchronous execution, finally, using join to synchronize to load is a good way to improve performance.
Reference source of this ASP. NET Tutorial: http://www.goberl.com/archive/item59.aspx