asp.net 2.0異步操作頁面
(一).簡單介紹實作原理
下圖左為未使用異步頁功能執行過程(Asp.net 1.0通常情況), 下圖右為使用了異步頁執行過程(Asp.net 2.0新增特性).
(Asp.net 1.0一般處理過程) (使用Asp.net 2.0新增特性異步頁功能處理過程)
從左圖中看出,在一個頁面整個請求的過程中, 一個線程始終為同一個頁面的請求服務.
而從右圖可以看出,在一個頁面請求的過程中, 可以由不同的線程為本頁面請求服務.
顯然,采用圖中方式在用戶端請求數量多時,網站整體效率較高. 因為:
1. 當未使用異步頁時,一個線程隻能為同一個頁面的請求服務. 即使頁面請求過程中處理其它的I/O等操作時,此線程也一直處于等待狀态. 當此頁面使用完此線程時,才将它放回到線程池. 線程數量是有限的! 是以當不使用線程時及時放回線池可以使系統性能大大提高!
2.當使用了異步頁功能時,如右圖中,開始Thread1是為頁面服務的,但當頁面處理其它的事情(比如I/O或調用其它 WebService) 時,Thread1被放回線程池, 此時Thread1可以為其它頁面請求服務了. 當此頁面執行完自己的操作回來後, Thread2接着為頁面請求服務,并不是使用的原來的線程Thread1. 這樣網站的伸縮性會更好.
(二).使用方法示例
I. 用 Page.AddOnPreRenderCompleteAsync 實作異步頁功能
a. Page标志加屬性: Async="true", 添加後代碼如下:
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="AsyncPage.aspx.cs"
Inherits="_Default" Async="true" %>
b. 背景異步頁面相關代碼 :
private WebRequest _request;
protected void Page_Load(object sender, EventArgs e)
...{
//注冊異步調用的Begin和End方法.
AddOnPreRenderCompleteAsync(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation)
);
}
//異步調用開始方法(當執行此方法時,目前線程就回到線程池,等待為其它請求服務).
IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
...{
_request = WebRequest.Create("http://blog.csdn.net/chengking/");
return _request.BeginGetResponse(cb, state);
}
//異步調用結束後的接收方法(異步操作執行完成後,會重新從線程池中取個線程為本頁面請求服務).
void EndAsyncOperation(IAsyncResult ar)
...{
string text;
using (WebResponse response = _request.EndGetResponse(ar))
...{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
...{
text = reader.ReadToEnd();
}
}
this.lbOupput.Text = text;
}
2. 資料庫對象SqlCommand實作異步調用功能.
a. Page标志加屬性: Async="true", 添加後代碼如下:
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="AsyncPage.aspx.cs"
Inherits="_Default" Async="true" %>
b. 背景代碼
public partial class AsyncVisitDatabase : System.Web.UI.Page
...{
//定義資料操作對象
private SqlConnection _connection;
private SqlCommand _command;
private SqlDataReader _reader;
protected void Page_Load(object sender, EventArgs e)
...{
if (!IsPostBack)
...{
//注冊事件Page_PreRender執行完成時執行方法
this.PreRenderComplete += new EventHandler(Page_PreRenderComplete);
/**注冊異步調用的Begin和End方法.
AddOnPreRenderCompleteAsync(
new BeginEventHandler(BeginAsyncOperation), new EndEventHandler(EndAsyncOperation));
}
}
//異步調用開始方法(當執行此方法時,目前線程就回到線程池,等待為其它請求服務).
IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
...{
//_request = WebRequest.Create("http://blog.csdn.net/chengking/");
//return _request.BeginGetResponse(cb, state);
string connect = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
_connection = new SqlConnection(connect);
_connection.Open();
_command = new SqlCommand("select * from gsjbxx", _connection);
return _command.BeginExecuteReader(cb, state);
}
//異步調用結束後的接收方法(異步操作執行完成後,會重新從線程池中取個線程為本頁面請求服務).
void EndAsyncOperation(IAsyncResult ar)
...{
_reader = _command.EndExecuteReader(ar);
//為了確定我得到了相應的資料并可以顯示在DATAVIEW中
table.Load(_reader);
}
protected void Page_PreRenderComplete(object sender, EventArgs e)
...{
this.GridView1.DataSource = table;
this.GridView1.DataBind();
}