C# 在Winform设计一个耗时较久的任务在后台执行时的状态提示窗口

2021-07-08 22:06

阅读:319

标签:==   top   name   progress   export   nim   for   技术   div   

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

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

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

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

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

技术分享图片

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

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

技术分享图片技术分享图片
  1         #region 显示应用程序作业状态
  2         /// 
  3         /// 后台作业线程定义模板类
  4         /// 
  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         /// 
 16         /// 以指定的定义开始一个线程运行作业任务
 17         /// 
 18         /// 
 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         /// 
 56         /// 取消后台任务的当前作业
 57         /// 
 58         /// 
 59         protected void CancelBgwork(BackgroundWorker tagBgwk)
 60         {
 61             tagBgwk.CancelAsync();
 62         }
 63 
 64         /// 
 65         /// 在此事件中调用工作方法
 66         /// 
 67         /// 
 68         /// 
 69         protected void BgwkBase1_DoWork(object sender, DoWorkEventArgs e)
 70         {
 71             ((Action)e.Argument).Invoke();
 72         }
 73 
 74         /// 
 75         /// 当后台任务运行进行进度报告时在状态窗口中显示状态
 76         /// 
 77         /// 
 78         /// 
 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         /// 
 92         /// 任务结束后(e.ProgressPercentage到100)关闭状态窗口
 93         /// 
 94         /// 
 95         /// 
 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;
        } 

 

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

C# 在Winform设计一个耗时较久的任务在后台执行时的状态提示窗口

标签:==   top   name   progress   export   nim   for   技术   div   

原文地址:https://www.cnblogs.com/imes/p/9732611.html


评论


亲,登录后才可以留言!