• ASP.NET 多线程 监控任务执行情况,并显示进度条


    关于多线程的基本概念和知识在本文中不多讲,而且我懂的也不是很透,说的太多误人子弟...对于我来说,做本文提到的功能够用就行,等实现其他效果不够用的时候,再深入研究

    推荐看园子里的两篇博客应该就有个基本的认识了:

    C#多线程(一):http://www.cnblogs.com/oshyn/p/3628686.html

    C#多线程(二):http://www.cnblogs.com/oshyn/p/3628792.html

    有时候我们在执行一个较长任务的时候,浏览器就好比处于“挂起”的状态,你得等待他把这一个事情处理完毕再去处理其他事情。

    那么比如说我们在执行一个反复插入数据库的操作,或者说执行大量的IO的操作的时候,这个过程往往是很耗时的,浏览器长时间不响应,对于客户的忍耐度是一个挑战。

    就好像你在安装游戏,只有一段文字提示你“正在安装,请稍后...”结果稍后了半个小时还在稍后,我不知道还要稍后多久,那我简直要疯了。

    所以这时候,如果能实时显示当前安装包正在做什么,复制什么文件,执行什么操作,已完成了多少,还剩下多少。这样的话,果然是极好的......

    以前也知道做这个功能的时候需要用到多线程来执行,基本道理和思路也懂,但是觉得多线程太麻烦,也不利于管理,因此很傻很天真地想了一个变相解决方案。

    基本想法是这样的:

    在执行任务的页面上放上两段JS代码,分别是: dowork()  checkstate()。其中,dowork() 以ajax方式提交请求,执行耗时长的操作,在操作过程中,不断把执行信息写入Session,而checkstate()以ajax的方式提交请求,执行获取session信息,接收到响应之后,写入div中显示出来。

    然而事实上是,在执行操作过程中,确实把任务信息写入了session,但是在dowork()请求的任务执行完毕之前,checkstate()请求的 读取session的操作是不会执行的,在dowork请求的任务执行完毕之后,checkstate()才会把最终的session值获取到。

    虽然知道可能是关于单线程的任务执行顺序问题,但是具体说不出来个门道(有哪位行家给分析分析。。。。。不胜感谢~)

    后来就只能做多线程来实现了,不多废话,直接上代码,注释写的都很详细

    主要分为两个页面 一个任务执行页面(Default) ,放置的按钮和信息呈现的容器,另一个页面是ajax请求页面(ajaxWork),用来执行请求操作和返回响应信息。

    1 <div>
    2     多线程监测任务执行情况示例
    3     <br /><br />
    4     <div class="msg"><div class="msg2"></div></div><br />
    5    <input type="button" onclick="create('');" value="开始执行" />&nbsp;&nbsp;&nbsp;&nbsp;
    6    <span></span>
    7     </div>
    Default.aspx
     1 function create(value) //写一个点击执行的函数,点击请求时,实参为空
     2     {
     3         var url="ajaxwork.aspx"; //初始化请求地址
     4         
     5         if(value!="") //判断如果实参不为空,则带参请求
     6         {
     7             url+="?key="+value
     8         }
     9         
    10         $.post(url,function(data)
    11         {
    12             var rs = new Function("return" + data)(); //转换JSON数据
    13             
    14             $("span").html("用时:"+rs.time+"&nbsp;&nbsp;&nbsp;&nbsp;已完成:"+rs.curr+"%"); //输出当前任务执行情况
    15             
    16             $(".msg2").css("width",rs.curr+"%"); // 控制进度条的加载
    17             
    18             if(rs.curr!="100") //判断如果没有查到100 则递归执行本方法
    19             {
    20                 create("1"); //带参请求(参数是多少无所谓,有就行),获取任务执行状态
    21             }
    22         });
    23     } 
    页面脚本
     1 using System;
     2 using System.Threading;
     3 
     4 public partial class AjaxWork : System.Web.UI.Page
     5 {
     6     static string count = "";
     7     protected void Page_Load(object sender, EventArgs e)
     8     {
     9         if (Request.QueryString["key"] == null) //判断如果为空 则为第一次请求 启动所要执行的任务
    10         {
    11             Start();
    12         }
    13         else //否则为请求任务执行的状态
    14         {
    15             ajaxResponse();
    16         }
    17     }
    18 
    19     /// <summary>
    20     /// 线程所要执行的查数方法
    21     /// </summary>
    22     private void DoWork()
    23     {
    24         count = "{'curr':'0','time':'00:00:00.0000000'}";//每次执行操作之前 初始化信息
    25         DateTime starttime = DateTime.Now; //获取任务开始的时间
    26         for (int i = 1; i < 101; i++) //从1查数到100
    27         {
    28             Thread.Sleep(100); // 为了不让程序一下执行完毕,设置线程的休眠,方便演示
    29             count = "{'curr':'" + i.ToString() + "','time':'" +(DateTime.Now - starttime) + "'}"; //反馈当前任务状态
    30         }
    31     }
    32 
    33     /// <summary>
    34     /// 线程启动
    35     /// </summary>
    36     private void Start()
    37     {
    38         Thread t = new Thread(DoWork); //实例化一个线程
    39         t.Start(); //启动
    40         Response.Write("{'curr':'0','time':'00:00:00.0000000'}"); //第一次请求返回初始化的信息
    41     }
    42 
    43     /// <summary>
    44     /// 获取任务的实时信息
    45     /// </summary>
    46     private void ajaxResponse()
    47     {
    48         Response.Write(count);
    49         Response.Flush();
    50         Response.End();
    51     }
    52 }
    ajaxWork.aspx.cs

    效果如下图:

    Demo下载:http://files.cnblogs.com/webconfig/Thread.rar 

    ==============================华丽的分割线==================================

    另外一个问题是,不知道为什么,在ajaxWork.aspx.cs中 声明的

     1 static string count = "" 

    如果你在每次执行线程的时候不进行初始化操作

    那么,你在第一次执行的时候,是正常的。但是,第一次执行完成之后,再次点按钮的时候,就会出现“抽筋”情况,具体可以下载demo看效果、

    断电调试,可以发现,第二次执行,count初始化的值,不是“”,而是第一次执行完毕之后的值:

    哪位高手给解释一下...

    忽然想到了生命周期的问题,原来一直以为,静态变量的生命周期是随着类的消亡而消亡的,对于ASP.NET,好像不是这样,看到一篇文章上提到,静态变量是application级别的,也就是说除非IIS重启,否则静态变量的值就是最后修改的值...也许可以解释这个问题吧

    文章地址:http://www.cnblogs.com/webconfig/p/3632260.html

    ---- 内容补充 -------------------------------------------------------------------------------

    今天下午有稍微研究了一下,也感谢@AllEmpty提出的观点,用静态变量传值确实会引发并发问题,当时为了图省事直接用静态变量传值了。后来想过用session传值,可是在新开辟的线程中使用session 总是引发异常,异常提示为:

    今天下午终于找到原因了,那就是在新开辟的线程使用session之前,需要在主线程中声明出session,否则就会引起该异常。

    所以我们修改代码:

    1,声明的静态变量count去掉,在线程启动之前在主线程声明出session

            if (Request.QueryString["key"] == null) //判断如果为空 则为第一次请求 启动所要执行的任务
            {
                Session["count"] = "";
                Start();
            }


    2,使用session记录状态:

     1     private void DoWork()
     2     {
     3         Session["count"] = "{'curr':'0','time':'00:00:00.0000000'}";//每次执行操作之前 初始化信息
     4         DateTime starttime = DateTime.Now; //获取任务开始的时间
     5         for (int i = 1; i < 101; i++) //从1查数到100
     6         {
     7             Thread.Sleep(100); // 为了不让程序一下执行完毕,设置线程的休眠,方便演示
     8             Session["count"] = "{'curr':'" + i.ToString() + "','time':'" + (DateTime.Now - starttime) + "'}"; //反馈当前任务状态
     9         }
    10     }


    3,响应session的值

    1         string countstr = "";
    2         if (Session["count"] != null)
    3         {
    4             countstr = Session["count"].ToString();
    5         }
    6         Response.Write(countstr);

    OK,并发问题解决!!!

    本文出自博客园:D调的码农

    转载请注明出处:http://www.cnblogs.com/webconfig/p/3632208.html

  • 相关阅读:
    web测试方法总结
    我认为测试应该掌握的SQL语句
    monkey(1)
    冒烟测试
    PC客户端测试总结
    常见测试点总结
    测试基本概念
    测试主要环节
    手机app常见bug积累
    MySQL面试题集锦
  • 原文地址:https://www.cnblogs.com/webconfig/p/3632208.html
Copyright © 2020-2023  润新知