PageAsyncTask
工作又一次到了轻松的时候,中午把平台的角色管理整理好后,简单的查询了一下关于异步的相关资料。在最近的客户要求中,他们想让BS系统有CS某些效果,如果仅仅把开发放到原有的基础,是无法给他们在性能和客户体验上达到一个他们期望的效果的,因此也找到了一种可以异步同时处理数据的处理机制,多少可以在性能上提高一点。
这个模型最大的好处在于可以在一次页面请求中处理多个异步任务,并且还可以用超时处理来避免在执行异步操作时出现的无响应情况。
懒惰惯了,就把主要的代码直接贴在上面,必要的注释都在代码里写上罢了!
详细信息可以参考:http://msdn.microsoft.com/zh-cn/developercenters/ms153491.aspx
首先,我们需要在页面的指令上设置异步的属性
1<%@ Page Language="C#" Async="true" AsyncTimeout="11" AutoEventWireup="true" CodeFile="async_Page.aspx.cs" Inherits="TextPage_Async_async_Page" %>
CS文件
1/// <summary>
2 /// 异步开始的时候调用的方法
3 /// </summary>
4 /// <param name="sender"></param>
5 /// <param name="e"></param>
6 /// <param name="cb"></param>
7 /// <param name="extraData"></param>
8 /// <returns>IAsyncResult</returns>
9 public IAsyncResult BeginInvoke(object sender, EventArgs e, AsyncCallback cb, object extraData)
10 {
11
12 //访问数据库,返回相关的用户信息
13 SqlConnection _con = new SqlConnection();
14 _con.ConnectionString = "Asynchronous Processing=true;Data Source=STAVON\\SQLEXPRESS;UID=sa;pwd=sa;database=SalePlatForm";
15 this._con.Open();
16
17 string sProcName = "select v_yhdm,v_xm,v_ddid from pt_yhmc ";
18 SqlCommand _command = new SqlCommand(sProcName, this._con);
19
20 //在这里我让它休眠10秒进行超时测试
21 Thread.Sleep(TimeSpan.FromSeconds(10));
22
23 return this._command.BeginExecuteReader(cb, extraData, CommandBehavior.CloseConnection);
24 }
25
26
27 /// <summary>
28 /// 在为超时前执行的方法
29 /// </summary>
30 /// <param name="result"></param>
31 public void EndInvoke(IAsyncResult result)
32 {
33
34 SqlDataReader reader = this._command.EndExecuteReader(result);
35
36 //对SqlDataReader的处理
37
38 reader.Close();
39 }
40
41
42 /// <summary>
43 /// 超时后没有反应调用的方法
44 /// </summary>
45 /// <param name="result"></param>
46 public void EndTimeOutInvoke(IAsyncResult result)
47 {
48 Response.Write("超时,未反应!");
49 }
50
51 /// <summary>
52 /// Buttons事件
53 /// </summary>
54 /// <param name="sender"></param>
55 /// <param name="e"></param>
56 protected void Button1_Click(object sender, EventArgs e)
57 {
58 //注册一个异步
59 PageAsyncTask task = new PageAsyncTask(BeginInvoke, EndInvoke, EndTimeOutInvoke, null);
60 Page.RegisterAsyncTask(task);
61 }
2 /// 异步开始的时候调用的方法
3 /// </summary>
4 /// <param name="sender"></param>
5 /// <param name="e"></param>
6 /// <param name="cb"></param>
7 /// <param name="extraData"></param>
8 /// <returns>IAsyncResult</returns>
9 public IAsyncResult BeginInvoke(object sender, EventArgs e, AsyncCallback cb, object extraData)
10 {
11
12 //访问数据库,返回相关的用户信息
13 SqlConnection _con = new SqlConnection();
14 _con.ConnectionString = "Asynchronous Processing=true;Data Source=STAVON\\SQLEXPRESS;UID=sa;pwd=sa;database=SalePlatForm";
15 this._con.Open();
16
17 string sProcName = "select v_yhdm,v_xm,v_ddid from pt_yhmc ";
18 SqlCommand _command = new SqlCommand(sProcName, this._con);
19
20 //在这里我让它休眠10秒进行超时测试
21 Thread.Sleep(TimeSpan.FromSeconds(10));
22
23 return this._command.BeginExecuteReader(cb, extraData, CommandBehavior.CloseConnection);
24 }
25
26
27 /// <summary>
28 /// 在为超时前执行的方法
29 /// </summary>
30 /// <param name="result"></param>
31 public void EndInvoke(IAsyncResult result)
32 {
33
34 SqlDataReader reader = this._command.EndExecuteReader(result);
35
36 //对SqlDataReader的处理
37
38 reader.Close();
39 }
40
41
42 /// <summary>
43 /// 超时后没有反应调用的方法
44 /// </summary>
45 /// <param name="result"></param>
46 public void EndTimeOutInvoke(IAsyncResult result)
47 {
48 Response.Write("超时,未反应!");
49 }
50
51 /// <summary>
52 /// Buttons事件
53 /// </summary>
54 /// <param name="sender"></param>
55 /// <param name="e"></param>
56 protected void Button1_Click(object sender, EventArgs e)
57 {
58 //注册一个异步
59 PageAsyncTask task = new PageAsyncTask(BeginInvoke, EndInvoke, EndTimeOutInvoke, null);
60 Page.RegisterAsyncTask(task);
61 }
上面的代码是否没有体现出我们有什么异步的事情,其实,我们可以同时处理很多的,我们这里需要在Buttons事件里添加更多的异步即可
1 protected void Button1_Click(object sender, EventArgs e)
2 {
3 // 创建一个异步
4 PageAsyncTask task1 = new PageAsyncTask(BeginInvoke1, EndInvoke1, EndTimeOutInvoke1, null);
5 // 创建一个异步
6 PageAsyncTask task2 = new PageAsyncTask(BeginInvoke2, EndInvoke2, EndTimeOutInvoke2, null);
7 // 创建一个异步
8 PageAsyncTask task3 = new PageAsyncTask(BeginInvoke3, EndInvoke3, EndTimeOutInvoke3, null);
9
10
11 RegisterAsyncTask(task);
12 ExecuteRegisteredAsyncTasks(); //
13 RegisterAsyncTask(task1);
14 ExecuteRegisteredAsyncTasks();
15 RegisterAsyncTask(task3);
16 ExecuteRegisteredAsyncTasks();
17 }
2 {
3 // 创建一个异步
4 PageAsyncTask task1 = new PageAsyncTask(BeginInvoke1, EndInvoke1, EndTimeOutInvoke1, null);
5 // 创建一个异步
6 PageAsyncTask task2 = new PageAsyncTask(BeginInvoke2, EndInvoke2, EndTimeOutInvoke2, null);
7 // 创建一个异步
8 PageAsyncTask task3 = new PageAsyncTask(BeginInvoke3, EndInvoke3, EndTimeOutInvoke3, null);
9
10
11 RegisterAsyncTask(task);
12 ExecuteRegisteredAsyncTasks(); //
13 RegisterAsyncTask(task1);
14 ExecuteRegisteredAsyncTasks();
15 RegisterAsyncTask(task3);
16 ExecuteRegisteredAsyncTasks();
17 }
注意:如果我们不使用ExecuteRegisteredAsyncTasks(),这三个任务便只好分享AsyncTimeout规定的运行时间了,如果第一个出现异常就会影响到以后所有的任务。感谢asp.net2.0给我们带来的方便,每次调用ExecuteRegisteredAsyncTasks()时,都会重置AsyncTimeout,这就可以让每个任务独自享受AsyncTimeout规定的时间了。