BackgroundWorker bw; private ManualResetEvent manualReset = new ManualResetEvent(true); private void button3_Click(object sender, EventArgs e) { using ( bw = new BackgroundWorker()) { bw.WorkerReportsProgress = true; bw.WorkerSupportsCancellation = true; bw.ProgressChanged += bw_ProgressChanged; bw.RunWorkerCompleted += bw_RunWorkerCompleted; bw.DoWork += bw_DoWork; //容許用戶指定顯示數據的範圍呢!因此須要把100做爲參數傳遞給計算過程 bw.RunWorkerAsync(100); } } //這時返回了主線程,因此能夠直接使用UI控件了 void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { //修改進度條的顯示。 //this.progressBarSum.Value = e.ProgressPercentage; //若是有更多的信息須要傳遞,可使用 e.UserState 傳遞一個自定義的類型。 //這是一個 object 類型的對象,您能夠經過它傳遞任何類型。 //咱們僅把當前 sum 的值經過 e.UserState 傳回,並經過顯示在窗口上。 string message = e.UserState.ToString(); label1.Text = message; } //e.Argument=bw.RunWorkerAsync("Hello World")的參數 void bw_DoWork(object sender, DoWorkEventArgs e) { System.Diagnostics.Debug.WriteLine("bw_DoWork"); BackgroundWorker bgWorker = sender as BackgroundWorker; //這裏的操做是在另外一個線程上完成的,不該該操做UI //在這裏執行耗時的運算。 int endNumber = 0; if (e.Argument != null) { endNumber = (int)e.Argument; } for (int i = 0; i <= endNumber; i++) { manualReset.WaitOne(); //若是ManualResetEvent的初始化爲終止狀態(true),那麼該方法將一直工做, //直到收到Reset信號。而後,直到收到Set信號,就繼續工做。 bgWorker.ReportProgress(i, "current num:" + i.ToString()); Thread.Sleep(500); //爲了方便演示 if (bgWorker.CancellationPending) { e.Cancel = true; System.Diagnostics.Debug.WriteLine("CancellationPending"); break; } } } //中止 private void button4_Click(object sender, EventArgs e) { bw.CancelAsync(); } //暫停/繼續 private void button5_Click(object sender, EventArgs e) { if (btnPause.Text == "暫停") { manualReset.Reset();//暫停當前線程的工做,發信號給waitOne方法,阻塞 btnPause.Text = "繼續"; } else { manualReset.Set();//繼續某個線程的工做 btnPause.Text = "暫停"; } }
請注意紅色字體, 採用信號量 ManualResetEvent來控制暫停/繼續函數
ManualResetEvent 容許線程經過發信號互相通訊。一般,此通訊涉及一個線程在其餘線程進行以前必須完成的任務。當一個線程開始一個活動(此活動必須完成後,其餘線程才能開始)時,它調用 Reset 以將 ManualResetEvent 置於非終止狀態,此線程可被視爲控制 ManualResetEvent。調用 ManualResetEvent 上的 WaitOne 的線程將阻止,並等待信號。當控制線程完成活動時,它調用 Set 以發出等待線程能夠繼續進行的信號。並釋放全部等待線程。一旦它被終止,ManualResetEvent 將保持終止狀態(即對 WaitOne 的調用的線程將當即返回,並不阻塞),直到它被手動重置。能夠經過將布爾值傳遞給構造函數來控制 ManualResetEvent 的初始狀態,若是初始狀態處於終止狀態,爲 true;不然爲 false。字體