PageAsyncTask是任务类,通过 Page.RegisterAsyncTask来注册,Page.ExecuteRegisteredAsyncTasks()调用
页面代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" AsyncTimeout="4" %>Asynchronous Task Example
后置代码:
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Threading;public partial class _Default : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) { // 定义异步任务. SlowTask slowTask1 = new SlowTask(); SlowTask slowTask2 =new SlowTask(); SlowTask slowTask3 =new SlowTask(); PageAsyncTask asyncTask1 = new PageAsyncTask(slowTask1.OnBegin, slowTask1.OnEnd, slowTask1.OnTimeout, "Async1", true); PageAsyncTask asyncTask2 = new PageAsyncTask(slowTask2.OnBegin, slowTask2.OnEnd, slowTask2.OnTimeout, "Async2", true); PageAsyncTask asyncTask3 = new PageAsyncTask(slowTask3.OnBegin, slowTask3.OnEnd, slowTask3.OnTimeout, "Async3", true); //注册页面异步任务. //单个任务如果超过页面定义的AsyncTimeout,就会调用Timeout委托 Page.RegisterAsyncTask(asyncTask1); Page.RegisterAsyncTask(asyncTask2); Page.RegisterAsyncTask(asyncTask3); DateTime tStart = DateTime.Now; // 执行注册的异步方法,会阻塞线程,直到所有注册方法执行完毕或者超时 Page.ExecuteRegisteredAsyncTasks(); DateTime tEnd = DateTime.Now; TaskMessage.InnerHtml = "Task1:"+slowTask1.GetAsyncTaskProgress() + "" + "Task2:"+slowTask2.GetAsyncTaskProgress() + "" + "Task3:"+slowTask3.GetAsyncTaskProgress() + ""+ "总开始时间:" + tStart + " 总结束时间:" + tEnd; } public class SlowTask { private static Random rand = new Random(); private String _taskprogress; private AsyncTaskDelegate _dlgt; // Create delegate. protected delegate void AsyncTaskDelegate(); public String GetAsyncTaskProgress() { return _taskprogress; } //实际执行的耗时操作 public void ExecuteAsyncTask() { //随即生产1-5秒模拟调用耗时 int second = rand.Next(1, 5); Thread.Sleep(TimeSpan.FromSeconds(second)); } //异步调用开始时调用 //此方法内一般不放耗时操作,而是内部新建线程执行 public IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object extraData) { _taskprogress = "开始时间: " + DateTime.Now + ". "; //这里定义耗时方法的委托,并开始异步执行 //虽然直接将耗时操作直接写在OnBegin可以有相同的效果,但是使用单独委托可以更灵活 //比如可以通过委托传递由外部定义的耗时操作 _dlgt = new AsyncTaskDelegate(ExecuteAsyncTask); IAsyncResult result = _dlgt.BeginInvoke(cb, extraData); return result; } // 异步调用结束时被调用 public void OnEnd(IAsyncResult ar) { _taskprogress += "完成时间: " + DateTime.Now; _dlgt.EndInvoke(ar); } //异步调用在指定时间未完成时被调用(即超时) public void OnTimeout(IAsyncResult ar) { _taskprogress += "异步操作超时"; } }}
用处:
使用异步任务可以最大限度利用多核服务器还可以利用ExecuteRegisteredAsyncTasks的阻塞功能实现简单Server-Push效果
思路:
服务端: 可以将异步方法放入某个类实例,方法中使用ManualResetEvent或其他同步类,阻塞方法执行,将类实例放入全局变量中,如Dictionary,当满足某些条件时(如某个请求),在全局变量中找出对应类,通过类的公开方法释放ManualResetEvent锁定返回是数据
客户端:根据服务端返回的信息作出不同反应,不管是超时还是正常得到数据,都再向服务器开ajax请求,等待服务器新的响应