在前文中,介绍了.NET下的多种异步的形式,在WEB程序中,天生就是多线程的,因此使用异步应该更为谨慎。本文将着重展开ASP.NET中的异步。
【注意】本文中提到的异步指的是服务器端异步,而非客户端异步(Ajax)。
对于HTTP的请求响应模型,服务器无法主动通知或回调客户端,当客户端发起一个请求后,必须保持连接等待服务器的返回结果,才能继续处理,因此,对于客户端来说,请求与响应是无法异步进行,也就是说无论服务器如何处理请求,对于客户端来说没有任何差别。
498)this.width=498;'' onmousewheel = ''javascript:return big(this)'' alt="" src="/uploadfile/201301/5/9815528791.png" />
那么ASP.NET异步指的又是什么,解决了什么问题呢?
在解释ASP.NET异步前,先来考察下ASP.NET线程模型。
ASP.NET线程模型
我们知道,一个WEB服务可以同时服务器多个用户,我们可以想象一下,WEB程序应该运行于多线程环境中,对于运行WEB程序的线程,我们可以称之为WEB线程,那么,先来看看WEB线程长什么样子吧。
我们可以用一个HttpHandler输出一些内容。
- public class Handler : IHttpHandler
- {
- public void ProcessRequest(HttpContext context)
- {
- context.Response.ContentType = "text/plain";
- var thread = Thread.CurrentThread;
- context.Response.Write(
- string.Format("Name:{0}\r\nManagedThreadId:{1}\r\nIsBackground:{2}\r\nIsThreadPoolThread:{3}",
- thread.Name,
- thread.ManagedThreadId,
- thread.IsBackground,
- thread.IsThreadPoolThread)
- );
- }
- public bool IsReusable
- {
- get {return true;}
- }
- }
你可以看到类似于这样的结果:
Name:
ManagedThreadId:57
IsBackground:True
IsThreadPoolThread:True
这里可以看到,WEB线程是一个没有名称的线程池中的线程,如果刷新这个页面,还有机会看到 ManagedThreadId 在不断变化,并且可能重复出现。说明WEB程序有机会运行于线程池中的不同线程。
为了模拟多用户并发访问的情况,我们需要对这个处理程序添加人为的延时,并输出线程相关信息与开始结束时间,再通过客户端程序同时发起多个请求,查看返回的内容,分析请求的处理情况。
- public void ProcessRequest(HttpContext context)
- {
- DateTime begin = DateTime.Now;
- int t1, t2, t3;
- ThreadPool.GetAvailableThreads(out t1, out t3);
- ThreadPool.GetMaxThreads(out t2, out t3);
- Thread.Sleep(TimeSpan.FromSeconds(10));
- DateTime end = DateTime.Now;
- context.Response.ContentType = "text/plain";
- var thread = Thread.CurrentThread;
- context.Response.Write(
- string.Format("TId:{0}\tApp:{1}\tBegin:{2:mm:ss,ffff}\tEnd:{3:mm:ss,ffff}\tTPool:{4}",
- thread.ManagedThreadId,
- context.ApplicationInstance.GetHashCode(),
- begin,
- end,
- t2 - t1
- )
- );
- }
我