原文地址:http://www.cnblogs.com/brave-heart/articles/1218343.html
ASP.NET 2.0 提供了大量新功能,其中包括聲明性資料繫結和主版頁面,成員和角色管理服務,非同步頁等,下面說說非同步頁。
當使用者發起對一個頁面的請求時,asp.net接受該請求並從線程池中為該請求分配一個線程。一個普通的頁面(或者說同步的頁面)
在請求期間保留該線程(該線程不能用於其他請求),如果請求的頁面需要訪問webservice或者ado調用資料庫等待返回(IO綁定),
那麼分配給請求的線程在調用返回之前出於掛起狀態。到了這裡大家應該知道了問題的所在,線程池裡的可用線程的數量是有限的,
如果有很多的使用者共同訪問這個頁面,那麼所有的請求都需要等待請求的線程阻塞直到調用返回,如果線程池的可用線程數為0,那麼
其他的請求排入隊列等待線程釋放,這樣請求等待較長的時間才能得到處理。
非同步頁為由 I/O 綁定的請求引起的問題提供優秀的解決方案。頁處理從線程池線程開始,當一個非同步 I/O 操作開始響應 ASP.NET
的訊號之後,該線程返回線程池。當該操作完成時,ASP.NET 從線程池提取另一個線程,並完成該請求的處理。由於線程池線程得
到了更高效的使用,因此提高了延展性。那些掛起等待 I/O 完成的線程現在可用於服務其他請求。直接的受益方是不執行長時間
I/O 操作並因此可以快速進出管線的請求。長時間等待進入管線會對此類請求的效能帶來不小的負面影響。(此段解釋來自msdn)
在ASP.NET 2.0中使用非同步頁,首先在aspx檔案的@ Page 指令添加 Async=“true” 屬性,如下所示
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Async="true" Inherits="WebApplication1._Default" %>
1.用 Page.AddOnPreRenderCompleteAsync 實現非同步頁功能
後台非同步頁面代碼 :
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
private System.Net.WebRequest _request;
protected void Page_Load(object sender, EventArgs e)
{
Page.AddOnPreRenderCompleteAsync(new BeginEventHandler(BeginMethod), new EndEventHandler(EndMethod));
}
IAsyncResult BeginMethod(object sender, EventArgs e, AsyncCallback cb, object state)
{
_request = System.Net.WebRequest.Create("http://www.hyey.com");
return _request.BeginGetResponse(cb, state);
}
void EndMethod(IAsyncResult ar)
{
string text;
using (System.Net.WebResponse response = _request.EndGetResponse(ar))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
text = reader.ReadToEnd();
}
}
this.Label1.Text = text;
}
}
}
2.非同步呼叫Webservice,
NET Framework 2.0 Web 服務代理支援兩種對 Web 服務進行非同步呼叫的機制。
一個是 .NET Framework 1.x 和 2.0 Web 服務代理中的每方法 Begin 和 End 方法。
另一個是僅由 .NET Framework 2.0 的 Web 服務代理提供的新 MethodAsync 方法和 MethodCompleted 事件。
如果一個 Web 服務有一個名為 Foo 的方法,那麼除了具有名為 Foo、BeginFoo 和 EndFoo 的方法外,
.NET Framework 版本 2.0 Web 服務代理還包括名為 FooAsync 的方法和名為 FooCompleted 的事件。
可以通過註冊 FooCompleted 事件的處理常式並調用 FooAsync 來非同步呼叫 Foo.
Webservice方法:
using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Data.SqlClient;
namespace WebService1
{
/// <summary>
/// Service1 的摘要說明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public DataSet returnDs()
{
System.Threading.Thread.Sleep(3000);
string connString = System.Configuration.ConfigurationManager.ConnectionStrings["sqlServerConnstring"].ToString();
SqlConnection con = new SqlConnection(connString);
SqlDataAdapter da = new SqlDataAdapter("select * from oauser", con);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
}
}
後台代碼:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
private localhost.Service1 _ws;
private DataSet _ds;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.PreRenderComplete += new EventHandler(Page_PreRenderComplete);
_ws = new WebApplication1.localhost.Service1();
_ws.returnDsCompleted += new WebApplication1.localhost.returnDsCompletedEventHandler(_ws_returnDsCompleted);
_ws.Url = "http://localhost:5983/Service1.asmx";// new Uri(Request.Url, "Service1.asmx").ToString();
_ws.UseDefaultCredentials = true;
_ws.returnDsAsync();
}
}
void _ws_returnDsCompleted(object sender, WebApplication1.localhost.returnDsCompletedEventArgs e)
{
_ds = e.Result;
}
protected void Page_PreRenderComplete(object sender, EventArgs e)
{
this.GridView1.DataSource = _ds;
this.GridView1.DataBind();
}
}
}
3.用 PageAsyncTask 實現非同步呼叫功能
後台代碼:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Net;
using System.IO;
namespace WebApplication1
{
public partial class WebForm2 : System.Web.UI.Page
{
private WebRequest _request;
protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask task = new PageAsyncTask(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation),
new EndEventHandler(TimeoutAsyncOperation), null);
RegisterAsyncTask(task);
}
IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
{
_request = WebRequest.Create("http://www.hyey.com");
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();
}
}
lbDisplay.Text = text.ToString();
}
//時間逾時執行操作
void TimeoutAsyncOperation(IAsyncResult ar)
{
lbDisplay.Text = "Failture!";
}
}
}
4.資料庫物件SqlCommand實現非同步呼叫
後台代碼:
1public partial class AsyncVisitDatabase : System.Web.UI.Page
2{
3 //定義資料操作對象
4 private SqlConnection _connection;
5 private SqlCommand _command;
6 private SqlDataReader _reader;
7
8 protected void Page_Load(object sender, EventArgs e)
9 {
10 if (!IsPostBack)
11 {
12 //註冊事件Page_PreRender執行完成時執行方法
13 this.PreRenderComplete += new EventHandler(Page_PreRenderComplete);
14
15 /**////註冊非同步呼叫的Begin和End方法.
16 AddOnPreRenderCompleteAsync(
17 new BeginEventHandler(BeginAsyncOperation),
18 new EndEventHandler(EndAsyncOperation)
19 );
20 }
21 }
22
23 //非同步呼叫開始方法(當執行此方法時,當前線程就回到線程池,等待為其它請求服務).
24 IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
25 {
26 string connect = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
27 _connection = new SqlConnection(connect);
28 _connection.Open();
29 _command = new SqlCommand("select * from sales", _connection);
30 return _command.BeginExecuteReader(cb, state);
31 }
32
33 //非同步呼叫結束後的接收方法(非同步作業執行完成後,會重新從線程池中取個線程為本頁面請求服務).
34 void EndAsyncOperation(IAsyncResult ar)
35 {
36 _reader = _command.EndExecuteReader(ar);
37 }
38
39 //事件Page_PreRender執行完成時執行方法,在這裡可以將非同步呼叫返回結果賦值給頁面上的控制項或者其它善後操作.
40 protected void Page_PreRenderComplete(object sender, EventArgs e)
41 {
42 GridView1.DataSource = _reader;
43 GridView1.DataBind();
44 }
45
46 public override void Dispose()
47 {
48 if (_connection != null)
49 _connection.Close();
50 base.Dispose();
51 }
52}