none
backgroundWorker練習的問題 RRS feed

  • 問題

  • 這幾天看了許多 backgroundWorker的資料
    以下是自己練習的程式法
    按下Start按鈕後,label中的值會從0開始一直增加,在按下Stop,便會停止
    雖然結果有照我想做得出現,但是我卻感覺到沒有用到RunWorkerCompleted
    public partial class Form1 : Form
        {
            int a = 0;
       
            public Form1()
            {
                InitializeComponent();
                backgroundWorker1.WorkerSupportsCancellation = true;//為了可以呼叫CancelAsync
            }
            private void Start_Click(object sender, EventArgs e)
            {
                backgroundWorker1.RunWorkerAsync();//執行backgroundWorker1_DoWork
               
            }
            private void Stop_Click(object sender, EventArgs e)
            {
               backgroundWorker1.CancelAsync();
            }
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                for (int i = 0; i < 1000000; i++)
                {
                    if (backgroundWorker1.CancellationPending)
                    {
                        e.Cancel = true;
                     //   MessageBox.Show(Convert.ToString(e.Result) + "看Resutl"); //無東西
                        break;
                    }
                    a = i;
                    this.Invoke(new Action(show));
                }
            }
            public void show()
            {
                this.label1.Text = Convert.ToString(a);
            }
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
               MessageBox.Show(Convert.ToString(e.Cancelled) + "<<看值");
            }
        }
    以下是參考的網站之一
    ------------------------------------------------------------------------------------------
    在BackgroundWorker的RunWorkerCompleted事件中檢查傳入此事件的RunWorkerCompletedEventArgs的Cancelled屬性值
    當這個值為Fasle則呼叫RunWorkerAsync方法重新引發DoWork事件重新開始一個新的背景執行緒;若為True則不再繼續。
    ------------------------------------------------------------------------
    若我將 e.Cancel = true;改為 false。 還是可以停止迴圈,但照參考資料說的話,為false則應該重新跑迴圈吧?
    另外,請問e.Result的內容應該是什麼呢? 我將它show出來但內容卻是空的
    若是自我練習的程式寫得不好,有比較推薦的網站可看嗎?
    以上問題請教各位
    2011年7月24日 上午 10:37

解答

  • C#和VB.NET 長的差不多吧,  你的問題主要也不是程式碼, 而是觀念, 而以下這一段 (http://www.dotblogs.com.tw/billchung/archive/2009/05/30/8597.aspx)

    (1) 將BackgroundWorker的WorkerSupportsCancellation屬性設為True,表示此BackgroundWorker物件可以支援取消作業的動作﹝也就是使它可以呼叫CancelAsync方法﹞。

      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
           BackgroundWorker1.WorkerReportsProgress = True
           BackgroundWorker1.WorkerSupportsCancellation = True
       End Sub

          (2) 在某一個特定事件中呼叫BackgroundWorker的CancelAsync方法﹝例如寫在某一個Button物件的Click事件中﹞。

       Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
           BackgroundWorker1.CancelAsync()
       End Sub

          (3) 在DoWork事件的程序中必要的位置建立檢查CancellationPending 屬性值的程序﹝當BackgroundWorker的CancelAsync方法被呼叫後,這個值將會成為True﹞,並在此一屬性值轉為True時將傳 入DoWork事件的DoWorkEventArgs的Cancel屬性值設為True。

     Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Dim CycleCount As Integer
            CycleCount = CType(e.Argument, Integer)
            Dim CycleObject As New StateObject
            CycleObject.CycleCount = CycleCount
            Dim i As Integer
            For i = 1 To 100
                CycleObject.i = i
                If BackgroundWorker1.CancellationPending = True Then  <==在此檢查CancellationPending
                    e.Cancel = True <==將DoWorkEventArgs.Cancel設為True
                    Exit Sub
                Else
                    BackgroundWorker1.ReportProgress(i, CycleObject)
                    System.Threading.Thread.Sleep(10)
                End If
            Next
            e.Result = CycleObject <==執行完畢將CycleObject傳遞給RunWorkerCompleted的RunWorkerCompletedEventArgs的Result屬性
       End Sub

    (4) 在BackgroundWorker的RunWorkerCompleted事件中檢查傳入此事件的 RunWorkerCompletedEventArgs的Cancelled屬性值﹝這個值就是由(3)所描述的 System.ComponentModel.DoWorkEventArgs的Cancel屬性值傳進來的﹞,當這個值為Fasle則呼叫 RunWorkerAsync方法重新引發DoWork事件重新開始一個新的背景執行緒;若為True則不再繼續。

               If Not (e.Error Is Nothing) Then
                   MessageBox.Show(e.Error.ToString)
               ElseIf e.Cancelled = True Then <==如果RunWorkerCompletedEventArgs.Cancelled為True則結束
                   Label4.Text = "結束於:" & Now.ToString("HH:mm:ss.fffffff")
               Else 
    <==如果RunWorkerCompletedEventArgs.Cancelled為False則繼續
                   Dim CycleObject As StateObject
                   CycleObject = (CType(e.Result, StateObject))
                   Dim CycleCount As Integer = 0
                   CycleCount = CycleObject.CycleCount + 1
                   BackgroundWorker1.RunWorkerAsync(CycleCount)
               End If

           這邊可能會有人有疑問為何在RunWorkerCompleted事件中不是直接檢查BackgroundWorker的CancellationPending屬性值,原因在於當DoWork事件執行完畢進入RunWorkerCompleted事件後,BackgroundWorker的CancellationPending屬性值將會恢復為False,所以不論怎麼檢查它都沒用的。

    不就是在講你發問最後方的問題嗎 ?


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2011年7月25日 上午 02:45
    版主
  •  

    http://www.dotblogs.com.tw/billchung/archive/2009/05/30/8597.aspx

     

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    • 已標示為解答 ask_learn 2011年7月26日 上午 01:16
    2011年7月24日 上午 11:24
    版主
  • 這是我之前學VB.net 的資料

    http://www.dotblogs.com.tw/jerrymow/archive/2010/10/26/18585.aspx     [VB.NET] 背景執行 - Backgroundworker + Progressbar

    http://www.dotblogs.com.tw/billchung/archive/2009/05/29/8592.aspx      多執行緒初探--使用BackgroundWorker(1)

    http://www.dotblogs.com.tw/billchung/archive/2009/05/30/8597.aspx      多執行緒初探--使用BackgroundWorker(2)

    至於C#.net的...我剛學還不是很熟語法,Sorry

    • 已標示為解答 ask_learn 2011年7月26日 上午 01:15
    2011年7月24日 下午 01:27

所有回覆

  •  

    http://www.dotblogs.com.tw/billchung/archive/2009/05/30/8597.aspx

     

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    • 已標示為解答 ask_learn 2011年7月26日 上午 01:16
    2011年7月24日 上午 11:24
    版主
  • 這是我之前學VB.net 的資料

    http://www.dotblogs.com.tw/jerrymow/archive/2010/10/26/18585.aspx     [VB.NET] 背景執行 - Backgroundworker + Progressbar

    http://www.dotblogs.com.tw/billchung/archive/2009/05/29/8592.aspx      多執行緒初探--使用BackgroundWorker(1)

    http://www.dotblogs.com.tw/billchung/archive/2009/05/30/8597.aspx      多執行緒初探--使用BackgroundWorker(2)

    至於C#.net的...我剛學還不是很熟語法,Sorry

    • 已標示為解答 ask_learn 2011年7月26日 上午 01:15
    2011年7月24日 下午 01:27
  • 我自己偏向委派,因為不是每種情況都能用 backgroundWorker 控制項,但是每種情況都能用委派。
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2011年7月24日 下午 02:39
  • 謝謝各位給的參考網站,不過我都有找到過了,請問有C#方面的範例嗎?

    另外,上面原本我是使用2008版本寫出來的,而到了2005中,this.Invoke(new Action(show)); 此行中,沒有Action的方法可使用(08有 Action 與Action<> 兩種可選,05只有後者),請問若我值改變,表單中也要改變,在2005版本中要如何改寫?

    2011年7月25日 上午 02:22
  • 你可以自己定義委派,Action 委派只是讓一些不會或不想自己定義委派的人用的。

    只是練會怎麼定義和使用委派,會對你未來使用 event 時有很大的幫助。


    小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
    雲端學堂Facebook: http://www.facebook.com/studyazure
    2011年7月25日 上午 02:41
    版主
  • C#和VB.NET 長的差不多吧,  你的問題主要也不是程式碼, 而是觀念, 而以下這一段 (http://www.dotblogs.com.tw/billchung/archive/2009/05/30/8597.aspx)

    (1) 將BackgroundWorker的WorkerSupportsCancellation屬性設為True,表示此BackgroundWorker物件可以支援取消作業的動作﹝也就是使它可以呼叫CancelAsync方法﹞。

      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
           BackgroundWorker1.WorkerReportsProgress = True
           BackgroundWorker1.WorkerSupportsCancellation = True
       End Sub

          (2) 在某一個特定事件中呼叫BackgroundWorker的CancelAsync方法﹝例如寫在某一個Button物件的Click事件中﹞。

       Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
           BackgroundWorker1.CancelAsync()
       End Sub

          (3) 在DoWork事件的程序中必要的位置建立檢查CancellationPending 屬性值的程序﹝當BackgroundWorker的CancelAsync方法被呼叫後,這個值將會成為True﹞,並在此一屬性值轉為True時將傳 入DoWork事件的DoWorkEventArgs的Cancel屬性值設為True。

     Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Dim CycleCount As Integer
            CycleCount = CType(e.Argument, Integer)
            Dim CycleObject As New StateObject
            CycleObject.CycleCount = CycleCount
            Dim i As Integer
            For i = 1 To 100
                CycleObject.i = i
                If BackgroundWorker1.CancellationPending = True Then  <==在此檢查CancellationPending
                    e.Cancel = True <==將DoWorkEventArgs.Cancel設為True
                    Exit Sub
                Else
                    BackgroundWorker1.ReportProgress(i, CycleObject)
                    System.Threading.Thread.Sleep(10)
                End If
            Next
            e.Result = CycleObject <==執行完畢將CycleObject傳遞給RunWorkerCompleted的RunWorkerCompletedEventArgs的Result屬性
       End Sub

    (4) 在BackgroundWorker的RunWorkerCompleted事件中檢查傳入此事件的 RunWorkerCompletedEventArgs的Cancelled屬性值﹝這個值就是由(3)所描述的 System.ComponentModel.DoWorkEventArgs的Cancel屬性值傳進來的﹞,當這個值為Fasle則呼叫 RunWorkerAsync方法重新引發DoWork事件重新開始一個新的背景執行緒;若為True則不再繼續。

               If Not (e.Error Is Nothing) Then
                   MessageBox.Show(e.Error.ToString)
               ElseIf e.Cancelled = True Then <==如果RunWorkerCompletedEventArgs.Cancelled為True則結束
                   Label4.Text = "結束於:" & Now.ToString("HH:mm:ss.fffffff")
               Else 
    <==如果RunWorkerCompletedEventArgs.Cancelled為False則繼續
                   Dim CycleObject As StateObject
                   CycleObject = (CType(e.Result, StateObject))
                   Dim CycleCount As Integer = 0
                   CycleCount = CycleObject.CycleCount + 1
                   BackgroundWorker1.RunWorkerAsync(CycleCount)
               End If

           這邊可能會有人有疑問為何在RunWorkerCompleted事件中不是直接檢查BackgroundWorker的CancellationPending屬性值,原因在於當DoWork事件執行完畢進入RunWorkerCompleted事件後,BackgroundWorker的CancellationPending屬性值將會恢復為False,所以不論怎麼檢查它都沒用的。

    不就是在講你發問最後方的問題嗎 ?


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2011年7月25日 上午 02:45
    版主
  • 謝謝大家給予的資料與意見

    原本我是以為
    if (backgroundWorker1.CancellationPending)
                    {
                        e.Cancel = true;
    }
     

     e.Cancel  = true時就會自動跳至RunWorkerCompleted而不用用break


    2011年7月26日 上午 01:15