同步處理模型雖直觀,但在高併發、長耗時請求(如呼叫外部 Web Service、大量資料庫查詢)下,會耗盡 ThreadPool 工作執行緒,導致伺服器效能驟降甚至崩潰。ASP.NET 2.0 引入非同步頁面模型,在 PreRender 與 PreRenderComplete 之間插入非同步點,讓長耗時作業釋放執行緒回 ThreadPool,完成後再取用執行緒續行,大幅提升併發承載能力。
在 @Page 指令設定 Async="true",告知 ASP.NET 使用 IHttpAsyncHandler 處理:
<%@ Page Async="true" Language="C#" %>
在 Page_Load 中註冊 Begin/End 方法組:
public partial class AsyncPage : System.Web.UI.Page
{
private WebRequest m_Request;
void Page_Load(object sender, EventArgs e)
{
AddOnPreRenderCompleteAsync(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation)
);
}
IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
{
m_Request = WebRequest.Create("https://www.example.com");
return m_Request.BeginGetResponse(cb, state);
}
void EndAsyncOperation(IAsyncResult ar)
{
string text;
using (WebResponse response = m_Request.EndGetResponse(ar))
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
text = reader.ReadToEnd();
Regex regex = new Regex("href\\s*=\\s*\"([^\"]*)\"", RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(text);
StringBuilder builder = new StringBuilder(1024);
foreach (Match match in matches)
{
builder.Append(match.Groups[1]);
builder.Append("<br/>");
}
Output.Text = builder.ToString();
}
}
PreRender 事件。BeginAsyncOperation,啟動非同步 I/O(Web Request、DB 查詢、檔案讀寫)。EndAsyncOperation。PreRenderComplete → Render 輸出結果。AsyncTimeout(預設 45 秒)內完成,否則拋出逾時例外。善用非同步頁面模型,是高併發 ASP.NET 應用程式突破 ThreadPool 瓶頸的關鍵鑰匙。