---------------201504170911更新---------------
更新內容:刪除bgwUI新增的Start方法,改為通過new修飾符+可選參數的方式同時覆蓋基類(BackgroundWorker)的RunWorkerAsync有參和無參倆方法。所以執行任務仍舊使用熟悉的RunWorkerAsync即可,忘掉蹩腳的Start。在此要感謝園友【新的開始】在評論中的指點,非常感謝!
---------------20150416原文(已更新)---------------
適用環境:.net 2.0+的Winform項目
這是上一篇【分享帶等待窗體的任務執行器一枚】的姊妹篇,建議先看看那篇文章了解一下相關背景。這里簡單介紹一下,兩個方案的共同目的都是在執行耗時任務時向用戶顯示一個模式窗體(我稱等待窗體),通過該窗體,任務可以向用戶報告執行進度,用戶也可以通過它干預任務的執行(也就是取消~如果任務允許被終止的話),等于就是在任務與用戶之間通過一個等待窗體來進行信息傳遞。這樣的需求應該是很常見的,注重用戶體驗的開發者都不可能讓用戶眼巴巴的面對一個卡死掉的界面,所以相信在類似場景中,大家都有各自的處理手段,例如異步執行任務,同時在業務窗體上弄個滾動條什么的,比如這樣:
這樣的手段有的猿友可能已經形成了很完善的通用方案,比我這個好上百倍都不止(在此也懇請路過老鳥不吝分享自己的或自己知道的現成好方案),有的猿友則可能還是具體情況具體處理,沒有一個通用方案,而我在做的,就是把我的方案分享出來,讓還沒有類似輪子的猿友拿去后,經過簡單處理就能實現效果,同時,也希望得到老鳥的指點,不斷完善。
上一篇分享的是一個叫做WaitUI的執行器,可以執行任何方法,使用簡單。而這一篇分享的是一個叫做BackgroundWorkerUI的東東(下文簡稱bgwUI),看名字就知道它是基于BackgroundWorker(下文可能簡稱bgw)組件實現的,所以如果你更習慣bgw的使用方式,這個適合你。先看一下使用效果:
private void button2_Click(object sender, EventArgs e){ //構造函數的另一個重載可傳入自定義等待窗體的實例 using (BackgroundWorkerUI bgwUI = new BackgroundWorkerUI(/*new MyWaitForm()*/)) { bgwUI.WorkerSupportsCancellation = true;//允許取消任務 bgwUI.DoWork += bgwUI_DoWork; //bgwUI.ProgressChanged += bgwUI_ProgressChanged;//雖然不需要,但仍可注冊ProgressChanged事件做其它事 bgwUI.RunWorkerCompleted += bgwUI_RunWorkerCompleted;//亦可注冊RunWorkerCompleted事件 bgwUI.RunWorkerAsync(); }}void bgwUI_DoWork(object sender, DoWorkEventArgs e){ BackgroundWorkerUI bgwUI = sender as BackgroundWorkerUI; //可以通過bgwUI的一組公開屬性和方法更新等待窗體 //bgwUI.CancelControlVisible = true;//設置取消任務的控件的可見性,默認該屬性會根據WorkerSupportsCancellation設置,但仍可以自由設置 bgwUI.BarStyle = ProgressBarStyle.Continuous;//設置滾動條樣式(默認是Marquee:循環梭動式) bgwUI.BarMaximum = 100; //設置滾動條值上限(默認是100) bgwUI.BarMinimum = 0; //設置滾動條值下限(默認是0) bgwUI.BarStep = 1; //設置滾動條步進幅度(默認是10) bgwUI.BarVisible = true; //設置滾動條是否可見(默認是true:可見) int i; for (i = Convert.ToInt32(e.Argument); i <= 100; i++) { if (bgwUI.CancellationPending)//老樣子,訪問CancellationPending獲知用戶是否取消任務 { e.Cancel = true; return; } //更新等待窗體不需要調用ReportProgress(),也不需要WorkerReportsProgress支持 bgwUI.WorkMessage = i.ToString();//設置任務進度描述 bgwUI.BarValue = i; //設置任務進度值 //CancelControlVisible可以反復設置,不受WorkerSupportsCancellation限制 //if (i % 10 == 0) { bgw.CancelControlVisible = false; } //else if (i % 5 == 0) { bgw.CancelControlVisible = true; } Thread.Sleep(50); } e.Result = i;}void bgwUI_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){ if (e.Cancelled) { MessageBox.Show("任務已取消!"); } else if (e.Error != null) { MessageBox.Show("任務有異常!" + e.Error.Message); } else { MessageBox.Show("任務完成。" + e.Result); }}使用示例
這里只講區別,沒講到的表示與bgw一致,不熟悉bgw用法的猿友請MSDN。先看類圖:
從類圖可看出bgwUI是繼承于bgw的子類。
BackgroundWorkerUI.cs僅包含classBackgroundWorkerUI,它用到的WaitForm.cs請到上一篇文章取用,幫園子節約點空間~哈。
using System;using System.ComponentModel;using System.Windows.Forms;namespace AhDung.WinForm{ /// <summary> /// 帶等待窗體的BackgroundWorker。報告進度用一組UI操作方法 /// </summary> public class BackgroundWorkerUI : BackgroundWorker { readonly IWaitForm waitForm;//等待窗體 Form activeForm;//等待窗體顯示前的活動窗體 bool formClosed;//指示等待窗體是否已被關閉 #region 一組操作等候窗體UI的屬性/方法 /// <summary> /// 獲取或設置進度描述 /// </summary> public string WorkMessage { get { if (waitForm.InvokeRequired) { return waitForm.Invoke(new Func<string>(() => waitForm.WorkMessage)) as string; } return waitForm.WorkMessage; } set { if (waitForm.InvokeRequired) { waitForm.BeginInvoke(new Action(() => waitForm.WorkMessage = value)); return; } waitForm.WorkMessage = value; } } /// <summary> /// 獲取或設置進度條可見性 /// </summary> public bool BarVisible { get { if (waitForm.InvokeRequired) { return Convert.ToBoolean(waitForm.Invoke(new Func<bool>(() => waitForm.BarVisible))); } return waitForm.BarVisible; } set { if (waitForm.InvokeRequired) { waitForm.BeginInvoke(new Action(() => waitForm.BarVisible = value)); return; } waitForm.BarVisible = value; } } /// <summary> /// 獲取或設置進度條動畫樣式 /// </summary> public ProgressBarStyle BarStyle { get { if (waitForm.InvokeRequired) { return (ProgressBarStyle)(waitForm.Invoke(new Func<ProgressBarStyle>(() => waitForm.BarStyle))); } return waitForm.BarStyle; } set { if (waitForm.InvokeRequired) { waitForm.BeginInvoke(new Action(() => waitForm.BarStyle = value)); return; } waitForm.BarStyle = value; } } /// <summary> /// 獲取或設置進度值 /// </summary> public int BarValue { get { if (waitForm.InvokeRequired) { return Convert.ToInt32(waitForm.Invoke(new Func<int>(() => waitForm.BarValue))); } return waitForm.BarValue; } set { if (waitForm.InvokeRequired) { waitForm.BeginInvoke(new Action(() => waitForm.BarValue = value)); return; } waitForm.BarValue = value;
新聞熱點
疑難解答