在这类程序中,我们提供的异步处理程序调用了IOCP异步方法,使得大量节省了WEB线程的占用,相比同步处理程序来说,并发量会得到相当大的提升。
【注意】前面提到,由于WEB线程属于线程池线程,因此,如果在线程池中加入任务,将同样会影响并发处理数。而在异步处理程序中,由线程池来完成异步将得不到任何本质上的提升,因此在异步处理程序中禁止操作线程池(ThreadPool.QueueUserWorkItem、 delegate.BeginInvoke,Task.Run等)。如果确定需要使用多线程来处理大量的计算,需要自己开启线程或实现自己的线程池。
- public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
- {
- return new Action(() =>
- {
- Thread.Sleep(1000);
- context.Response.Write("OK");
- }).BeginInvoke(cb, extraData);
- }
上面的代码将无法达到异步的效果。
498)this.width=498;'' onmousewheel = ''javascript:return big(this)'' alt="" src="/uploadfile/201301/5/7415529507.png" />
虽然等待工作交由另一线程去操作,但是该线程与WEB线程性质相同,同样会导致其他请求阻塞。
【思考】如果我们的程序中的确需要有大量的计算,那么可以考虑将这些计算提取到独立的应用服务器中,然后通过网络IOCP异步调用,达到WEB服务器的高吞吐量与系统的平行扩展性。
典型应用场景二:长连接消息推送。
一般来说,在WEB中获取服务器消息,采用轮询的方式,这种方式不可避免会有延时,当我们需要即时消息的推送时(如WEBIM),需要用到长连接。
长连接方式,由客户端发起请求,服务器端接收后暂停处理并保持连接,当需要发送消息给客户端时,输出内容并结束处理,客户端得到消息或者超时后,再次发起连接。如此达到在HTTP协议上服务器消息即时推送到客户端的目的。
498)this.width=498;'' onmousewheel = ''javascript:return big(this)'' alt="" src="/uploadfile/201301/5/5815529523.png" />
在这种情况下,我们希望服务器尽可能长时间保持连接,如果采用同步处理程序,则连接数受到服务器线程数的限制,而异步处理程序则可以很好的解决这个问题。异步处理程序开始时,收集相关信息,并放入集合后返回异步结果。当需要向这个客户端发送消息时,从客户端集合中找到需要发送的目标,发送完成即可。
首先,我们需要对客户端进行标识,这个标识往往采用sessionid来做,本例中简单起见,通过客户端传递参数获取。
- public class WebAsyncResult : IAsyncResult
- {
- private AsyncCallback _callback;
- public WebAsyncResult(AsyncCallback cb, HttpContext context, string clientID)
- {
- Context = context;
- ClientID = clientID;
- _callback = cb;
- }
- //当异步完成时调用该方法
- public void SetComplete()
- {
- IsCompleted = true;
- if (_callback != null)
- {
- _callback(this);
- }
- }
我