首先需要明白的是同步和异步的区别,撇开生硬的定义不谈,就以线程IO请求来说,同步就是让一个线程A去进行IO请求,当请求没有完成之前,线程A一直不离不弃的在那里死等,直到得到请求,可以想象,如果运用同步到请求队列中,这将是一个耗时费力的工作。但是如果采用异步请求的时候,当线程A去进行IO请求的时候,没有得到请求结果之前,线程A可以去做别的事情。这样,利用这种方式,可以提高服务器的吞吐量,MSDN中对此解释如下: 异步操作通常用于执行完成时间可能较长的任务,如打开大文件、连接远程计算机或查询数据库。异步操作在主应用程序线程以外的线程中执行。应用程序调用方法异步执行某个操作时,应用程序可在异步方法执行其任务时继续执行。 那么在WebForm编程模型中,怎么实现异步呢? 首先来看看Asp.net生命周期和异步生命周期的对比(图片来源网络,如有侵权,请告知): |
其实很简单,只要在页面首部写上Async="true" 的标记即可让这个页面异步起来。
至于在页面中实现异步,这里有两个方法:AddOnPreRenderCompleteAsync和RegisterAsyncTask
首先,对于AddOnPreRenderCompleteAsync方法,代码如下:
1 using System.IO; 2 3 namespace AsyncPagesApp 4 { 5 public partial class _Default : System.Web.UI.Page 6 { 7 FileStream fileStream; //文件流 8 protected void Page_Load(object sender, EventArgs e) 9 { 10 if(IsPostBack) 11 return; 12 fileStream = new FileStream(@"\\***\20111122_EXO.txt", FileMode.Open); //文件流位置 13 AddOnPreRenderCompleteAsync(BeginAsyncOperation, EndAsyncOperation);//注册异步事件 14 } 15 private IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state) //开始异步 16 { 17 int bufferSize = 99999999; 18 byte[] buffer = new byte[bufferSize]; 19 return fileStream.BeginRead(buffer, 0, bufferSize, cb, state); 20 } 21 private void EndAsyncOperation(IAsyncResult ar) //异步结束 22 { 23 int fileReadByte = (int)fileStream.EndRead(ar); //得到异步执行结果 24 fileStream.Flush(); 25 fileStream.Close(); //关闭流 26 Label1.Text = fileReadByte.ToString(); 27 } 28 } 29 }
对于RegisterAsyncTask方法,代码如下:
1 using System; 2 using System.Web.UI; 3 using System.IO; 4 namespace AsyncPagesApp 5 { 6 public partial class RegisterAsyncTaskPage : System.Web.UI.Page 7 { 8 FileStream fileStream; 9 protected void Page_Load(object sender, EventArgs e) 10 { 11 if(IsPostBack) 12 return;//准备文件流读取 13 fileStream = new FileStream(@"\\***\20111122_EXO.txt", FileMode.Open); //申明异步任务 14 PageAsyncTask task = new PageAsyncTask(BeginAsync, EndAsync, TimeoutAsync, true);//注册异步任务 15 RegisterAsyncTask(task);//开始运行 16 ExecuteRegisteredAsyncTasks(); 17 }//开始运行 18 protected IAsyncResult BeginAsync(object sender, EventArgs e, AsyncCallback cb, object state) 19 { 20 int bufferSize = 99999999; 21 byte[] buffer = new byte[bufferSize]; 22 return fileStream.BeginRead(buffer, 0, bufferSize, cb, state); 23 }//运行结束 24 protected void EndAsync(IAsyncResult ar) 25 { 26 int fileReadByte = (int)fileStream.EndRead(ar); //运行结束 27 fileStream.Flush(); 28 fileStream.Close();//关闭 29 Label1.Text = fileReadByte.ToString(); 30 } 31 protected void TimeoutAsync(IAsyncResult ar) 32 { 33 Label1.Text = "server Invalid! "; 34 fileStream.Close(); 35 } 36 } 37 }
从上面的代码,可以发现这两种异步方式的区别,第一种方式提供了一种比较简便的编程模型,只需要Begin***和End***方法即可,但是第一种方式不支持超时方式,并且,在第一种异步方式编程的内部,某些变量的值是不能获取的,比如说User.Identity.Name,但是在第二种异步方法中,是可以获取到的。同时需要说明的是在第二种异步方法中,最后一个参数如果设置为True的话,可以让多个任务并行运行。