2016年3月2日 星期三

C# Backgroundworker進階教學(Thread.Sleep的正確使用)

System.Threading.Thread.Sleep相信各位Winform的程式員都知道是什麼,就是停止運作一定的時間,但作為一個已進化的菜鳥,不能夠在正常情況可使用,最好是在BackgroundWorker內用,就能夠神不知鬼不覺,因為當你不在BackgroundWorker內使用,該死的界面就會顯示(Not Responding)的字句,客戶就會走來找你,問是不是死機啊‧‧‧以下是一個簡單的例子。

1‧創建一個WINFORM界面,並新增4個Control─label1、button1、toolStripProgressBar1、backgroundworker1

*backgroundworker1不是User Interface*

2‧background新增Event Handler

WorkerReportsProgress一定要set成true,否則不能加入ProgressChanged Event。
this.backgroundWorker1.WorkerReportsProgress = true;
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);

3‧ProgressChanged Event

主要是紀錄進度,除了toolStripProgressBar,toolStripLabel也是能夠更改的。
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
   // The progress percentage is a property of e
   toolStripProgressBar1.Value = e.ProgressPercentage;
}

4‧DoWork Event

DoWork這裡會轉換label1的文字,ProgressBar亦會紀錄進度,Thread.Sleep在這裡使用。
在function內接觸Control類的,需要加入Invoke(Action),才可運行,否則會彈出跨線程錯誤。
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
   Args arg = (Args)e.Argument;
   string a = arg.a;
   string b = arg.b;
   backgroundWorker1.ReportProgress(0);
   label1.Invoke(new Action(() => { label1.Text = b; }));
   backgroundWorker1.ReportProgress(30);
   Thread.Sleep(1000);
   backgroundWorker1.ReportProgress(60);
   label1.Invoke(new Action(() => { label1.Text = a; }));
   backgroundWorker1.ReportProgress(100);
   Thread.Sleep(1000);
   backgroundWorker1.ReportProgress(0);
   button1.Invoke((Action)(() => button1.Enabled = true));
}

5‧Args Class

在DoWork拿取Control的數值、文字是比較困難的,最好的方法是由外面掉Parameter入DoWork Function,所以先創建一個Class。
簡簡單單,看得明白就好。
internal class Args
{
   internal string a { get; set; }
   internal string b { get; set; }
}

5‧Button1 Action

Button1用來啟動BackgroundWorker,而且將剛才的Class放入DoWork這個Function裡面。

private void button1_Click(object sender, EventArgs e)
{
   button1.Enabled = false;
   var args = new Args() { a = "YES", b = "NO" };
   backgroundWorker1.RunWorkerAsync(args);
}

6‧結果

運行時可以見到label1由"No"變成"Yes",而ProgressBar亦會上升,為時大約5秒,而且UI不會出現Not Responding字樣,所以成功了。



這個Backgroundworker、progressbar的進階教學也完結了,多謝各位。

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。