介绍
当服务器接收到一个Request请求时会从线程池中获取一个线程并将页面请求分配给该线程
一个普通的页面在请求期间会一直占用该线程该线程不能用于处理其他请求。
如果一个慢速操作例如当该请求查询远程数据库并等待调用返回时则分配给它的线程在调用返回前会始终处于等待的闲置状态
这种情况会限制可伸缩性,因为线程池中的可用线程是有限的。如果处理请求的所有线程都因等待完成而阻塞,则会有多余的请求排队等待这些线程的释放。
最好的情况是出现吞吐量降低,因为需要更长的等待才能处理请求。最糟糕的情况是队列被填满而服务器无法处理后续请求就会提示 503“服务器不可用”错误。
异步页面的出现为此类问题提供了简洁的方案,页面处理要在线程池中的一个线程上进行但是当一个异步操作开始进行时,该线程会返回原先的线程池,
操作完成后,服务器会从线程池中获取另一个线程来完成处理请求。
这样,线程池的线程使用率得到提高,可伸缩性也因此得以增强。
那些本来要等待 操作完成而阻塞的线程此时可以用于处理其他请求。
比较常用的异步处理场景
- sqlcommand
- i/o操作
- socket
- webrequest
- webservcie
与ajax异步的效果区别
- 异步页面增加的是处理请求的数量,线程池线程得到了高效的使用,提高了可伸缩性
- 而ajax是在页面加载完成之后根据返回结果调用回调函数操作dom完成数据加载
- 例如,一个费时的异步io方法,需要费时10s,那么用户要想看到页面,起码在10s以上。
View Code
using System;
using System.Web;
using System.Data;
using System.Web.UI;
using System.Configuration;
using System.Data.SqlClient;
namespace exp
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
Page.AddOnPreRenderCompleteAsync(new BeginEventHandler(BeginRequest), new EndEventHandler(EndRequest));
}
IAsyncResult BeginRequest(object sender, EventArgs e, AsyncCallback callback, object state)
{
SqlConnection cn = new SqlConnection("server=10.255.255.120\\db12846,14330;uid=readuser;pwd=password;database=productpage;asynchronous processing=true");
SqlCommand cmd = cn.CreateCommand();
cmd.CommandText = "select top 100 product_id,product_name,original_price,sale_price from products_core";
cn.Open();
return cmd.BeginExecuteReader(callback,cmd,CommandBehavior.CloseConnection);
}
void EndRequest(IAsyncResult res)
{
if (!res.IsCompleted)
{
res.AsyncWaitHandle.WaitOne();
return;
}
SqlDataReader reader = (res.AsyncState as SqlCommand).EndExecuteReader(res);
this.rptProd.DataSource = reader;
this.rptProd.DataBind();
reader.Close();
}
}
}

浙公网安备 33010602011771号