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;
        } 

 

這樣,比較簡單的就完成了一個友好提示功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM