多線程學習筆記(三) BackgroundWorker 暫停/繼續

        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。字體

相關文章
相關標籤/搜索