Asp.Net异步页处理

         当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程。一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求。如果一个同步请求成为 I/O 绑定(例如,如果它调用一个远程 Web 服务或查询一个远程数据库,并等待调用返回),那么分配给该请求的线程在调用返回之前处于挂起状态。这影响了可伸缩性,原因是线程池的可用线程是有限的。如果所有请求处理线程全部阻塞以等待 I/O 操作完成,则其他请求排入队列等待线程释放。最好的情况是吞吐量减少,因为请求等待较长的时间才能得到处理。最坏的情况则是该队列填满,并且 ASP.NET 因 503Server Unavailable错误使后续请求失败。
 
  异步页为由 I/O 绑定的请求引起的问题提供优秀的解决方案。页处理从线程池线程开始,但是当一个异步 I/O 操作开始响应 ASP.NET 的信号之后,该线程返回线程池。当该操作完成时,ASP.NET 从线程池提取另一个线程,并完成该请求的处理。由于线程池线程得到了更高效的使用,因此提高了可伸缩性。那些挂起等待 I/O 完成的线程现在可用于服务其他请求。直接的受益方是不执行长时间 I/O 操作并因此可以快速进出管线的请求。长时间等待进入管线会对此类请求的性能带来不小的负面影响。

1  在aspx页面中的@Page指令引入Async="true"属性。

例如:
<%@ Page Language="C#" AutoEventWireup="true" Async="true" MasterPageFile="~/Site.master" CodeFile="AsyncPage.aspx.cs" Inherits="AsyncPage" %>
<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Title">
    Asynchronous Pages
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Descript" runat="server">
    This Page demonstrates how to use Page.AddOnPreRenderComplete to perform asynchronous
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="Main" runat="server">
    <asp:Label ID="OutPut" runat="server"></asp:Label>
</asp:Content>

2  在后台cs文件中实现 IhttpAsyncHandler。接下来,您在该页生存期的早期(例如,在 Page_Load 时)调用新的 Page.AddOnPreRenderCompleteAsync 方法来注册一个 Begin 方法和一个 End 方法,如以下代码所示:

protected void Page_Load(object sender, EventArgs e)
    {
        AddOnPreRenderCompleteAsync(
            new BeginEventHandler(BeginAsyncOperation),
            new EndEventHandler(EndAsyncOperation)
        );
    }

 接下来的操作比较有趣。该页经历其常规处理生命周期,直到 PreRender 事件刚刚引发之后。然后,ASP.NET 调用使用 AddOnPreRenderCompleteAsync 注册的 Begin 方法。Begin 方法的任务是启动诸如数据库查询或 Web 服务调用的异步操作,并立即返回。此时,分配给该请求的线程返回到线程池。此外,Begin 方法返回 IAsyncResult,它允许 ASP.NET 确定异步操作完成的时间,这个时候 ASP.NET 从线程池提取线程并调用 End 方法。当 End 返回之后,ASP.NET 执行该页生命周期其余的部分,包括呈现阶段。在 Begin 返回以及调用 End 之间,该请求处理线程可以自由地服务于其他请求,直至调用 End 且延迟呈现为止。由于 2.0 版的 .NET Framework 提供多种执行异步操作的方式,因此,您甚至无需实现 IasyncResult。反之,Framework 替您实现。
 
  列子整体代码。响应页包含一个 ID 为Output的 Label 控件。该页使用 System.Net.HttpWebRequest 类提取MSDN的内容。然后,它分析返回的 HTML,并将它发现的全部 HREF 目标列表写出到 Label 控件。

前台aspx:
<%@ Page Language="C#" AutoEventWireup="true" Async="true" MasterPageFile="~/Site.master" CodeFile="AsyncPage.aspx.cs" Inherits="AsyncPage" %>
<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Title">
    Asynchronous Pages
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Descript" runat="server">
    This Page demonstrates how to use Page.AddOnPreRenderComplete to perform asynchronous
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="Main" runat="server">
    <asp:Label ID="OutPut" runat="server"></asp:Label>
</asp:Content>

后台cs

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;
using System.Text;
using System.Text.RegularExpressions;

//Asp.Net异步回调 请求页面处理
public partial class AsyncPage : System.Web.UI.Page
{
    private WebRequest _request;
    protected void Page_Load(object sender, EventArgs e)
    {
        AddOnPreRenderCompleteAsync(
            new BeginEventHandler(BeginAsyncOperation),
            new EndEventHandler(EndAsyncOperation)
        );
    }
    public IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
    {
        _request = WebRequest.Create("http://www.sina.com.cn");
        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();
            }
        }
        Regex regex = new Regex("href\\s*=\\s*\"([^\"]*)\"",RegexOptions.IgnoreCase);
        MatchCollection matches = regex.Matches(text);
        StringBuilder builder = new StringBuilder(1024);
        foreach (Match match in matches)
        {
            builder.Append(match.Groups[1]);
            builder.Append("<br/>");
        }
        OutPut.Text = builder.ToString();
    }
}
原文地址:https://www.cnblogs.com/VirtualMJ/p/757412.html