• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

asp.net后台多线程异步处理时的进度条实现一(Ajax+Ashx实现以及封装成控件的实现) ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

  (更新:有的同学说源代码不想看,说明也不想看,只想要一个demo,这边提供一下:http://url.cn/LPT50k (密码:TPHU))

 

  工作好长时间了,这期间许多功能也写成了不少的控件来使用,但是,都只是为了代码的结构清析一些而已。而这一次,我决定完成一个我一直在网上寻找却没寻找到的功能。就是,在异步(比如说,后台的数据库备份、后台的文件加解密这类操作)时,前台假死的情况。asp自带了updatePanel,里面可以放一个自带的progress控件,怎么说呢,这就是一个显示而已,而且根本不能动。当你在备份数据的时候,你点备份,然后上面显示“请等待....”,这叫progress,我擦。不过,微软官方给了解释了,说许多人习惯了观察浏览器状态栏上面的进度条,我想说那个条子好假,不信你试试。

 

  好了,下面来说一下我做的这个东西,当然,我先用ajax+ashx的方式想办法让它实现,下面是我设计前期自己画的一张图:

这张图上面有错误,但是,作为我的第一个想法,我觉得它功不可没,后面的图都是在它的基础上修改而来了,它也代表了我的初始想法,以及相关的知识残缺。

 

  图中已经可以把我大部分的想法表达出来了,当然会有人说,通常ajax轮询进度都是这么实现的。但是,却没有人将它封装成服务器控件。

  先说图中明显的错误:

    1、异步操作的时候,一旦请求终断,线程则无法再访问到session,这是一个致命的异常。因为,我本来打算以session来保存信息,并依靠session的机制来释放我已经保存的内容,可以省下好多流程与精力,但事实证明,我还是太年轻了~~。所以,我改用了application,写就了我的第一个后台ashx文件:

  

 1 public class AjaxAction : IHttpHandler, IReadOnlySessionState
 2     {
 3 
 4         public void ProcessRequest(HttpContext context)
 5         {
 6             context.Response.ContentType = "text/plain";
 7             if (context.Request.QueryString["Action"] != null)
 8             {
 9                 string command = context.Request.QueryString["Action"].ToString();
10                 System.Reflection.MethodInfo method = this.GetType().GetMethod(command);
11                 if (method != null)
12                 {
13                     method.Invoke(this, new object[] { context });
14                 }
15             }
16         }
17 
18         public void ProgressMothed(HttpContext context)
19         {
20             string guid = HttpContext.Current.Session.SessionID.ToString().Trim() + DateTime.Now.ToString("HHmmssffffff").Trim();
21             Thread th = new Thread(
22                 delegate()
23                 {
24                     for (int i = 0; i < 101; i++)
25                     {
26                         Thread.Sleep(100);
27                         context.Application[guid] = i;
28                         context.Response.Write(i.ToString());
29                     }
30                     
31                 }
32                 );
33             th.IsBackground = true;
34             try
35             {
36                 th.Start();
37                 context.Application.Add(guid, 0);
38                 context.Response.Write(guid);
39             }
40             catch (Exception ex)
41             {
42                 context.Response.Write("-1");
43             }
44         }
45         public void GetPercentMethod(HttpContext context)
46         {
47             try
48             {
49                 string guid = context.Request.QueryString["guid"].ToString();
50                 string per = context.Application[guid].ToString();
51                 context.Response.Write(per);
52             }
53             catch (Exception ex)
54             {
55                 context.Response.Write("-1");
56             }
57         }
58         public bool IsReusable
59         {
60             get
61             {
62                 return false;
63             }
64         }
 1 <script type="text/javascript"> 8     function AjaxMethod() {
 9         $.ajax({
10             url:location.href,
12             data: { Action: "ProgressMethod", ts: (new Date).getTime() },
13             success: function (data) {
14                 if (!(data == undefined || data == null || data == "")) {
15                     if (data != "-1") {
16                         AjaxGetPercent(data);
17                     } else {
18                         alert("此处理过程暂时无法连接,请稍后再试");
19                     }
20                 } else {
21                     alert("访问的处理不存在,请刷新后重试["+data+"]");
22                 }
23             }
24         });
25     }
26     function AjaxGetPercent(guid) {
27         $.ajax({
28             url: location.href,
30             data: { Action: "GetPercentMethod",guid:guid, ts: (new Date).getTime() },
31             success: function (data) {
32                 if (data != "-1") {
33                     if (data < 100) {
34                         $("#progress_ensleep_pb").css("display", "block");
35                         $("#progress_ensleep_text").html(data);
36                         $("#progress_ensleep_pgress").css("width", data + "%");
37                         setTimeout(AjaxGetPercent(guid), 50);
38                     } else {
39                         $("#progress_ensleep_pgress").css("width", "100%");43                         $("#progress_ensleep_text").html(100);
45                     }
46                 } else {
47                     alert("操作过程中出现异常,请重试");
48                 }
49             }
50         });
51     }
52 </script>

  可以看出,我完全按照我当初的想法来做的,只是加了一些容错机制,试验了一下,一个进度条在一个页面上,完成正常,并且加入了样式,非常好看。但是,如果一个页面上有十个怎么办?这种情况很多,很常见。而且,每一个方法都要写在ashx这个文件中,人家aspx.cs里面的东西凭什么往你ashx里面写?这样的结果当然就是,我的整个项目乱成面条(打了两局dota的时间煮的面条)——看看不清,理理不起来。想做成引入型的,只能做成控件。

  但是,做成控件有以下几个问题:

    1、一个页面上要放n个控件,前台要为每个控件完成情况执行相应的js回调函数。

    2、这个控件正在执行的时候,如果页面回传,完了之后,它必须继续跑,并且像没回传一样。

    3、事件!!!!

  先说第三个,事件:

  因为控件的目的是执行异步操作,可以看见,我使用了子线程来处理,而子线程是由委托控件。一开始我是想,这是控件,我为什么放着事件不用呢?我把这个子线程要用到的方法写成一个事件,由aspx.cs给这个事件写方法体,不就可以了么?事实证明,我又秀了一次我的年轻~~~,ajax回传的时候,根本就不会触发控件的这一类事件,之所以说这一类,是因为像on_load()这些还是触发的,但是,它是要处理管道管理的,而按钮的onclick之类的无法触发,因为ajax没有带viewstate过来。这就导致了,我的每一次ajax都不是postback,我了个擦啊~~0~~。然后我开始收集信息,就像三国杀逆风时你要数数剩余的牌,dota逆风时你要看一看地图上每一个红点闪现时它的装备,war3时拼死一个步兵或者大g小g冲进对面看一看对面建筑一样……,然后我发现,我可以用的只有ajax带一的context以及session这两个东西,当然后台还有一个application,我不把它放入我的考虑范围(你被虐惨了,你会想着你家还有一个牛逼的泉水么?)。然后我使用了委托,是的,写了一个委托成员。然后爆露出一个成员方法以释放被使用的application(编码习惯良好,反正比南京的空气要好得多~~~)。

  再说第第一个和第二个,

    js回调方法:我把这个抛给使用者写了,放在aspx页面,只要把函数设到控件的属性里面就可以了,然后在控件生成的时候,将这个方法名写到回调的地方。然后为控件生成的所有的js方法都起唯一的名字,即 将控件的ClientID放在方法的后面。这使得一个页面上可以实现多个控件。

    回调后状态的还原继续:我在控件的On_load方法里面,每一次都查找看是否有可用的application,如果有,即会生成一个$(documeent).ready(function(){...}),里面会直接调用对percent(即当前进度)的ajax请求。

  下面上代码:

 1 <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="AjaxProgress.ascx.cs" Inherits="ESLib.Controls.AjaxProgress" %>
 2 <script type="text/javascript">if (!window.jQuery) alert("使用AjaxProgress必须引用jquery!");</script>
 3 <script type="text/javascript">
 4     $(document).ready(function () {
 5         <% if (this.guid != null && this.guid != "")
 6            {%>
 7                <%="AjaxGetPercent_"+this.ClientID+"('"+this.guid+"');"%>
 8            <%}%>
 9     });
10     function AjaxMethod_<%=this.ClientID%>(clientid) {
11         $.ajax({
12             url:location.href,
13             //content: "Action=ProgressMethod&ClientID=" + clientid + "&ts=" + (new Date).getTime(),
14             data: { Action: "ProgressMethod", ClientID: '<%=this.ClientID%>', ts: (new Date).getTime() },
15             success: function (data) {
16                 if (!(data == undefined || data == null || data == "")) {
17                     if (data != "-1") {
18                         AjaxGetPercent_<%=this.ClientID%>(data);
19                     } else {
20                         alert("此处理过程暂时无法连接,请稍后再试");
21                     }
22                 } else {
23                     alert("访问的处理不存在,请刷新后重试["+data+"]");
24                 }
25             }
26         });
27     }
28     function AjaxGetPercent_<%=this.ClientID%>(guid) {
29         $.ajax({
30             url: location.href,
31             //content: "Action=GetPercentMethod&ClientID=" + clientid + "&gu + (new Date).getTime(),
32             data: { Action: "GetPercentMethod", ClientID: '<%=this.ClientID%>',guid:guid, ts: (new Date).getTime() },
33             success: function (data) {
34                 if (data != "-1") {
35                     if (data < 100) {
36                         $("#progress_ensleep_pb_<%=this.ClientID%>").css("display", "block");
37                         $("#progress_ensleep_text_<%=this.ClientID%>").html(data);
38                         $("#progress_ensleep_pgress_<%=this.ClientID%>").css("width", data + "%");
39                         setTimeout(AjaxGetPercent_<%=this.ClientID%>(guid), 50);
40                     } else {
41                         $("#progress_ensleep_pgress_<%=this.ClientID%>").css("width", "100%");
42                         if ("<%=this.CloseWhenEnd.Trim()%>" == "true") {
43                             $("#progress_ensleep_pb_<%=this.ClientID%>").css("display", "none");
44                         }
45                         $("#progress_ensleep_text_<%=this.ClientID%>").html(100);
46                         <%=this.JsSuccessCallBack%>
47                     }
48                 } else {
49                     alert("操作过程中出现异常,请重试");
50                 }
51             }
52         });
53     }
54 </script>
55 <style type="text/css">
56         .progressContentensleep{
57             background-color:blue;
58             height:30px;
59             float:left;
60             width:300px;
61         }
62         .progressInnerensleep {
63             background-color:green;
64             height:30px;
65         }
66         .progressSpanensleep{
67             color:white;
68             height:30px;
69             line-height:30px;
70             margin-top:-30px;
71         }
72     </style>
73 <div>
74     <div style="display:none">
75     </div>
76     <div id='progress_ensleep_pb_<%=this.ClientID.Trim() %>' class='<%=this.OuterCssClass %>' style='display: none'>
77         <div id='progress_ensleep_pgress_<%=this.ClientID.Trim() %>' class='<%=this.InnerCssClass %>' style="width:0%">
78         </div>
79          <div id='progress_ensleep_span_<%=this.ClientID.Trim() %>' class='<%=this.TextCss %>'><%=this.WarmText.Substring(0,this.WarmText.IndexOf('{')) %><span id='progress_ensleep_text_<%=this.ClientID.Trim() %>'"></span><%=this.WarmText.Substring(this.WarmText.IndexOf('}')+1,this.WarmText.Length-this.WarmText.IndexOf('}')-1) %></div>
80     </div>
81 </div>

控件的cs代码:

  1 using
                      

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
ASP.NET 程序优化发布时间:2022-07-10
下一篇:
ASP.NET MVC TempData使用心得(转)发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap