zoukankan      html  css  js  c++  java
  • C# 在Winform设计一个耗时较久的任务在后台执行时的状态提示窗口

    很多时候,我们需要在窗体中执行一些耗时比较久的任务。比如:循环处理某些文件,发送某些消息等。。。

    单纯的依靠状态栏,用户体验不佳,按下功能按钮后得不到有效的提醒,小白用户绝对会电话给你说“我点了以后就没反应了...”。

    因此,对于响应时间可能超过5秒以上的事件,有必要增加一个显眼的提示框(在屏幕中央,最好有动图,如果有需要的话还可以设置为模态)。

    此实现大体分三部分(重点在于使用BGWK解决UI阻塞的问题):

    1、设计好提醒页面(一个转圈圈的动图Image,一个状态文字Label,再加一个进度条):

    如果不需要动图,则这个窗体无需编写代码。

    2、显示这个窗体的代码,目前放在基类窗体中被子类窗体继承。

      1         #region 显示应用程序作业状态
      2         /// <summary>
      3         /// 后台作业线程定义模板类
      4         /// </summary>
      5         protected class BgwkDef
      6         {
      7             public BackgroundWorker TagBgwk;
      8             public Action RunningAction;
      9             public int TProgMinimum = 0;
     10             public int TProgStep = 1;
     11             public int TProgMaximum = 100;
     12             public string RunningStatus;
     13         }
     14 
     15         /// <summary>
     16         /// 以指定的定义开始一个线程运行作业任务
     17         /// </summary>
     18         /// <param name="sBgwkDef"></param>
     19         protected void BeginBgwork(BgwkDef sBgwkDef)
     20         {
     21             if (frmStatus == null)
     22             {
     23                 frmStatus = new FrmStatus();
     24             }
     25             if (frmStatus != null)
     26             {
     27                 frmStatus.ProgMain.Minimum = sBgwkDef.TProgMinimum;
     28                 frmStatus.ProgMain.Step = sBgwkDef.TProgStep;
     29                 frmStatus.ProgMain.Maximum = sBgwkDef.TProgMaximum;
     30                 frmStatus.TopLevel = false;
     31                 frmStatus.Parent = this;
     32                 frmStatus.Show();
     33                 frmStatus.BringToFront();
     34                 frmStatus.Left = (this.Width - frmStatus.Width) / 2;
     35                 frmStatus.Top = (this.Height - frmStatus.Height) / 2 - 90;
     36             }
     37             if (sBgwkDef.RunningAction == null)
     38             {
     39                 MyMsg.Warning("系统后台任务必须指定作业方法,请检查!");
     40                 return;
     41             }
     42 
     43             BackgroundWorker tagBgwk = sBgwkDef.TagBgwk ?? new BackgroundWorker();
     44             tagBgwk.WorkerSupportsCancellation = true;
     45             tagBgwk.WorkerReportsProgress = true;
     46             tagBgwk.DoWork -= BgwkBase1_DoWork;
     47             tagBgwk.DoWork += BgwkBase1_DoWork;
     48             tagBgwk.ProgressChanged -= BgwkBase1_ProgressChanged;
     49             tagBgwk.ProgressChanged += BgwkBase1_ProgressChanged;
     50             tagBgwk.RunWorkerCompleted -= BgwkBase1_RunWorkerCompleted;
     51             tagBgwk.RunWorkerCompleted += BgwkBase1_RunWorkerCompleted;
     52             tagBgwk.RunWorkerAsync(sBgwkDef.RunningAction);
     53         }
     54 
     55         /// <summary>
     56         /// 取消后台任务的当前作业
     57         /// </summary>
     58         /// <param name="tagBgwk"></param>
     59         protected void CancelBgwork(BackgroundWorker tagBgwk)
     60         {
     61             tagBgwk.CancelAsync();
     62         }
     63 
     64         /// <summary>
     65         /// 在此事件中调用工作方法
     66         /// </summary>
     67         /// <param name="sender"></param>
     68         /// <param name="e"></param>
     69         protected void BgwkBase1_DoWork(object sender, DoWorkEventArgs e)
     70         {
     71             ((Action)e.Argument).Invoke();
     72         }
     73 
     74         /// <summary>
     75         /// 当后台任务运行进行进度报告时在状态窗口中显示状态
     76         /// </summary>
     77         /// <param name="sender"></param>
     78         /// <param name="e"></param>
     79         protected void BgwkBase1_ProgressChanged(object sender, ProgressChangedEventArgs e)
     80         {
     81             if (frmStatus != null)
     82             {
     83                 frmStatus.ProgMain.Value = e.ProgressPercentage > frmStatus.ProgMain.Maximum ? frmStatus.ProgMain.Maximum : e.ProgressPercentage;
     84                 frmStatus.ProgMain.PerformStep();
     85                 frmStatus.LabMessage.Text = e.UserState.ToString();
     86                 frmStatus.LabMessage.Refresh();
     87             }
     88             SetMainStatus(e.UserState.ToString());
     89         }
     90 
     91         /// <summary>
     92         /// 任务结束后(e.ProgressPercentage到100)关闭状态窗口
     93         /// </summary>
     94         /// <param name="sender"></param>
     95         /// <param name="e"></param>
     96         protected void BgwkBase1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
     97         {
     98             if (e.Cancelled)
     99             {
    100             }
    101             if (frmStatus != null)
    102             {
    103                 frmStatus.Close();
    104                 frmStatus = null;
    105             }
    106         }
    107         #endregion
    View Code

    3、调用第2步的显示方法的代码(实际工作场合)。

            private void CmdExport_Click(object sender, EventArgs e)
            {
                //创建或匹配一个BackgroundWorker,初始化一个耗时任务
                BackgroundWorker bgwk = new BackgroundWorker();
                BgwkDef bgwkDef = new BgwkDef()
                {
                    RunningAction = delegate () { ExportIvoice(bgwk); },
                    TagBgwk = bgwk
                };
                BeginBgwork(bgwkDef);
            }
    
            //耗时比较久的工作任务方法
            private void ExportIvoice(BackgroundWorker bgwk)
            {
                bgwk.ReportProgress(1, "正在尝试导出到EXCEL...");
                //打开Excel等操作
                //各种操作......
                if ("出错了")
                {
                    CancelBgwork(bgwk);//取消任务
                    MyMsg.Exclamation("开启报表文件失败,请检查!");
                    return;
                }
                //继续运行......
                //最后完成任务
                bgwk.ReportProgress(100, "导出成功!");
                return;
            } 

    这样,比较简单的就完成了一个友好提示功能。

  • 相关阅读:
    URL 中使用 Base64 编码
    一个简单实用的C#日志类(第二版)
    C# 对象XML序列化
    VS2010安装项目的系统必备中添加.NET 2.0
    .NET Framework 4 安装程序
    使用ExeConfigurationFileMap读写配置文件
    C# 生成 XML
    Bug管理工具和测试管理工具介绍
    Android学习系列(19)App离线下载
    Android拓展系列(5)CyanogenMod源码下载和编译(Android ROM定制基础篇)
  • 原文地址:https://www.cnblogs.com/imes/p/9732611.html
Copyright © 2011-2022 走看看