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}