如何在ASP.NET页面中使用异步任务(PageAsyncTask)

在页面加载期间,可能有些操作是要比较耗用时间的(例如调用外部资源,要长时间等待其返回),正常情况下,这个操作将一直占用线程。而大家知道,ASP.NET在服务端线程池中的线程数是有限的,如果一直占用的话,就会导致其他操作需要等待。

ASP.NET 2.0中,提供了一种异步页的技术。微软有一个专门的文档介绍这个技术

看看下面这个图,很重要

  

【注意】ASP.NET的异步机制与windows From的异步机制有一个根本区别,就是因为Response不可以分布发送到客户端的,所以,这个异步的效果对客户端来说可能是效果不明显的。也就说客户还是一样等待所有的操作完成之后才能看到页面。但是,使用了异步技术后,服务器端的线程能得到更好的利用,从另外一个层面是提高性能。

下面我用一个简单的例子来演示如何使用该技术

1. 页面需要启用async支持

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="LxSrcWebApp.WebForm1" Async="true" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title></title>

    <link rel="Stylesheet" href="default.css" />

</head>

<body>

    <form id="form1" runat="server">

    <div  id="mydiv" runat="server">

    </div>

    </form>

</body>

</html>

 

2.通过一个独立的类型(class)定义长时间执行任务的操作

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

 

namespace LxSrcWebApp

{

    class LongTimeTask

    {

        public string Result = string.Empty;

        public HelloWorldHandler handler;

        public delegate string HelloWorldHandler();

        public string HelloWorld()

        {

            Thread.Sleep(5000);

            return "Hello,world";

        }

 

        public IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object extraData)

        {

            handler = new HelloWorldHandler(this.HelloWorld);

            return handler.BeginInvoke(cb, extraData);

        }

 

        public void OnEnd(IAsyncResult ar)

        {

            Result = handler.EndInvoke(ar);

        }

 

        public void OnTimeout(IAsyncResult ar)

        {

            Result = "超时了";

        }

    }

}

 

3. 在页面的Page_Load事件中,注册异步任务

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

 

namespace LxSrcWebApp

{

    public partial class WebForm1 : System.Web.UI.Page

    {

        LongTimeTask task;

 

        protected void Page_Load(object sender, EventArgs e)

        {

            task = new LongTimeTask();

            PageAsyncTask asynctask = new PageAsyncTask(task.OnBegin, task.OnEnd, task.OnTimeout, null);

            RegisterAsyncTask(asynctask);

        }

 

        protected override void OnPreRenderComplete(EventArgs e)

        {

            mydiv.InnerHtml = task.Result;

        }

    }

}

4. 在页面的OnPreRenderComplete的方法里面接收异步任务的结果

protected override void OnPreRenderComplete(EventArgs e)

{

    mydiv.InnerHtml = task.Result;

}

 

 

【注意】值得一说的是,如果是调用Web Service,也可能会需要比较长时间,但因为Web Service的异步调用有内部的支持。不需要我们像上面这样复杂。

例如,有下面这样一个服务

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Services;

using System.Threading;

 

namespace demoService

{

    /// <summary>

    /// Summary description for Service1

    /// </summary>

    [WebService(Namespace = "http://tempuri.org/")]

    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

    [System.ComponentModel.ToolboxItem(false)]

    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.

    // [System.Web.Script.Services.ScriptService]

    public class Service1 : System.Web.Services.WebService

    {

 

        [WebMethod]

        public string HelloWorld()

        {

            Thread.Sleep(5000);

            return "Hello World";

        }

    }

}

 

添加对其引用之后,我们在页面代码中大致是这样的,前台aspx代码是一样的

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

 

namespace LxSrcWebApp

{

    public partial class WebForm2 : System.Web.UI.Page

    {

        LongTimeTask task;

 

        protected void Page_Load(object sender, EventArgs e)

        {

            localhost.Service1 proxy = new localhost.Service1();

            //绑定一个完成事件

            proxy.HelloWorldCompleted += new localhost.HelloWorldCompletedEventHandler(proxy_HelloWorldCompleted);

            proxy.HelloWorldAsync();

        }

 

        void proxy_HelloWorldCompleted(object sender, localhost.HelloWorldCompletedEventArgs e)

        {

            mydiv.InnerHtml = e.Result;

        }

    }

}

 

可以看到,这种方式简单多了。

 

其他内置支持异步的场景还有IO操作。这里就不一一描述了

 修改自:http://www.cnblogs.com/chenxizhang/archive/2009/07/12/1522069.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值