设为首页
加入收藏
站内地图
旧版入口
当前位置:首页 > 站长学院 > 网络编程 > ASP.NET

ASP.NET 2.0 中的异步页功能应用 4

作者:佚名 出处:网络转载 时间:11-10 点击:

内容载入中...
     异步任务
  
    MethodAsync 是从异步页进行多个异步 Web 服务调用并延迟呈现阶段直到所有调用完成的一个简便方法。但如果您想在一个异步页中执行若干异步 I/O 操作,而且这些操作不涉及 Web 服务,那该如何呢? 这么说,可以反过来生成一个 IAsyncResult,它可以返回到 ASP.net 以允许它了解最后一个调用何时完成的吗? 幸运的是,答案是否定的。
  
    在 ASP.NET 2.0 中,System.Web.UI.Page 类引入了另一个方法来简化异步操作: ReGISterAsyncTask。RegisterAsyncTask 比 AddOnPreRenderCompleteAsync 具有四个优势。首先,除了 Begin 和 End 方法,RegisterAsyncTask 还允许您注册当异步操作长时间无法完成时调用的超时方法。您可以通过在该页的 @ Page 指令中包含 AsyncTimeout 属性以声明性方式设置超时。AsyncTimeout="5" 将超时设置为 5 秒。第二个优势是,您可以在一个请求中多次调用 RegisterAsyncTask 来注册若干异步操作。和使用 MethodAsync 一样,ASP.NET 延迟呈现该页,直到所有操作完成。第三,您可以使用 RegisterAsyncTask 的第四个参数将状态传递给 Begin 方法。最后,RegisterAsyncTask 将模拟、区域性和 HttpContext.Current 注入 End 和 Timeout 方法。正如本文前面提到的,使用 AddOnPreRenderCompleteAsync 注册的 End 方法的情况则不然。
  
    在其他方面,依赖于 RegisterAsyncTask 的异步页与依赖于 AddOnPreRenderCompleteAsync 的异步页相类似。它仍然需要 @ Page 指令(或等效的编程指令,它会将该页的 AsyncMode 属性设置为 true)中的 Async=“true” 属性,而且它仍然与平时一样通过 PreRender 事件执行,此时调用使用 RegisterAsyncTask 注册的 Begin 方法,而且进一步保持请求处理直到最后一个操作完成。例如,图 7 中的代码隐藏类在功能上与图 1 中的等效,但是它使用 RegisterTaskAsync 而非使用 AddOnPreRenderCompleteAsync。请注意名为 TimeoutAsyncOperation 的超时处理程序,如果 HttpWebRequest.BeginGetRequest 长时间无法完成,将调用该处理程序。相应的 .ASPx 文件包括一个将超时间隔设置为 5 秒的 AsyncTimeout 属性。还请注意传给 RegisterAsyncTask 的第四个参数(可用于将数据传送到 Begin 方法)的 null。
  
  图7
  
  using System;
  using System.Web;
  using System.Web.UI;
  using System.Web.UI.WebControls;
  using System.Net;
  using System.IO;
  using System.Text;
  using System.Text.RegularExpressions;
  public partial class AsyncPageTask : 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://msdn.microsoft.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();
      }
    }
  
    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();
   }
  
   void TimeoutAsyncOperation(IAsyncResult ar)
   {
    Output.Text = "Data temporarily unavailable";
   }
  }
  
  
  
    RegisterAsyncTask 的主要优势在于,它允许异步页引发多个异步调用,并延迟呈现直到所有调用完成。它也很好地适用于单个异步调用,而且它提供了 AddOnPreRenderCompleteAsync 不具有的超时选项。如果生成一个只进行一个异步调用的异步页,您可以使用 AddOnPreRenderCompleteAsync 或 RegisterAsyncTask。但对于放置两个以上异步调用的异步页,RegisterAsyncTask 极大地简化了您的操作。
  
    由于超时值是每页而非每调用设置,因此您可能想知道是否能改变单个调用的超时值。简单的回答是否。您可以通过以编程方式修改页的 AsyncTimeout 属性,逐个请求地更改超时,但是您无法将不同超时分配给从同一请求初始化的不同调用。
  包装它
  
    现在,您已经了解了 ASP.NET 2.0 中异步页的实质。它们在即将推出的 ASP.NET 版本中非常易于实现,并且其体系结构允许您在一个请求中批处理多个异步 I/O 操作,并延迟该页的呈现直到所有操作完成。通过与异步 ADO.NET 和 .NET Framework 中的其他新异步功能相结合,异步 ASP.NET 页针对因充满线程池而限制可伸缩性的 I/O 绑定请求问题提供了解决方案。
  
    当生成异步页时最后需要注意的一点是,不应该启动来自 ASP.NET 使用的同一线程池的异步操作。例如,在页的异步点调用 ThreadPool.QueueUserWorkItem 会起反作用,因为该方法来自线程池,从而导致纯粹获取用于处理请求的零线程。相反,调用内置于 Framework 中的异步方法(例如,方法 HttpWebRequest.BeginGetResponse 和 SqlCommand.BeginExecuteReader)通常认为是安全的,因为这些方法倾向于使用完成端口实现异步行为。
  
    。

收藏本文:
】【打印页面】【推荐给朋友】【关闭窗口

站长学院

推荐信息