none
[VB 2005]BackgroundWorker 取消執行的問題 RRS feed

  • 問題

  • 各位老師好

    我在表單 Frm1 中

    Public Class Frm1

    Public BackgroundWorker1 As BackgroundWorker

     

    Private Sub Frm1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

     

    BackgroundWorker1 = New BackgroundWorker BackgroundWorker1.WorkerReportsProgress = True BackgroundWorker1.WorkerSupportsCancellation = True AddHandler BackgroundWorker1.DoWork, New DoWorkEventHandler(AddressOf BackgroundWorker1_DoWork) AddHandler BackgroundWorker1.ProgressChanged, New ProgressChangedEventHandler(AddressOf BackgroundWorker1_ProgressChanged) AddHandler BackgroundWorker1.RunWorkerCompleted, New RunWorkerCompletedEventHandler(AddressOf BackgroundWorker1_RunWorkerCompleted) BackgroundWorker1.RunWorkerAsync() Private Sub

     

     

    Frm1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed

    BackgroundWorker1.CancelAsync()

    BackgroundWorker1 = Nothing

    MajorForm.Timer1.Enabled = True

     

    問題在我關閉這個表單的時候 出現了

     

     

     

    我想來想去不曉得是哪裡出了問題

     

    請教各位老師

     

    謝謝各位

     

    2008年4月16日 上午 02:15

解答

  • HI,

     

    您還要加一個結束迴圈的動作, 例如Exit Do, Exit For, 或Exit While, 例如:

     

    If BackgroundWorker1.CancellationPending = Ture Then
                    e.Cancel = True
                    '取消BackgroundWorker執行中的工作

                    Exit For

    Else

        做要回圈執行的動作
     End If

     

    tihs

    2008年4月19日 上午 03:18

所有回覆

  • HI,

     

    1) 首先呼叫BackgroundWorker的CancelAsync方法的地方可以考慮換到FormClosing事件處理程序

    2) 在BackgroundWorker的DoWork事件必須判斷BackgroundWorker是否有被取消:

     

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As 

                               System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
               If BackgroundWorker1.CancellationPending Then
                    e.Cancel = True
                    '取消BackgroundWorker執行中的工作
               End If
    End Sub

     

    換句話說, 取消BackgroundWorker執行的工作要自己做, 不是呼叫BackgroundWorker的CancelAsync方法就可以解決的

     

    tihs

    2008年4月16日 上午 02:32
  • tihs大大

     

    我Backgroundworker是做成迴圈式的

    也就是Backgroundworker   完成後

    我在做一次Run

     

     

    我找了妳的方法把關閉事件要引發的程式碼移到 Closeing 中

    然後再Dowork 事件內加入

    Code Snippet
      If BackgroundWorker1.CancellationPending Then
                    e.Cancel = True
                    '取消BackgroundWorker執行中的工作
               End If

     

     

     

    可是我發現當我關閉表單後,也就是取消執行緒後

    BackgroundWork還在工作中

    因為他顯示 isBusy

     

    這是我的疑問

    謝謝老師

     

    2008年4月16日 上午 03:34
  • 給你一個小範例參考,利用 Timer 定時去執行呼叫的動作,
    如果下次執行時間到了,上一次動作如果仍未做完,新的呼叫就會被取消。

    // 宣告
    private static readonly BackgroundWorker bk1 = new BackgroundWorker();

    // 設定
    bk1.WorkerSupportsCancellation = true;
    bk1.DoWork += bk1_DoWork;
    bk1.RunWorkerCompleted += bk1_RunWorkerCompleted;

    // 呼叫
    if (bk1.IsBusy)
    {
        bk1.CancelAsync();
        Thread.Sleep(100);
    }
    else
    {
        bk1.RunWorkerAsync();
    }

    private static void bk1_DoWork(object sender, DoWorkEventArgs e)
    {
        if (bk1.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
    }
    2008年4月16日 上午 04:41
  • HI,

     

    您有做取消BackgroundWorker執行中的工作的動作嗎?

     

     If BackgroundWorker1.CancellationPending Then
                    e.Cancel = True
                    '取消BackgroundWorker執行中的工作
     End If

     

    tihs

    2008年4月17日 上午 01:28
  •  

    有阿

     

    可是她BackgroundWorker1的狀態還是在isBusy

     

     

    2008年4月17日 上午 04:04
  • Hi,

    如果DoWork裡面有跑迴圈之類的也要去檢查取消的動作喔,也就是說要把檢查的動作放到迴圈裡面去判斷。

    2008年4月17日 上午 07:57
    版主
  • 我是這樣寫ㄉ

     

    If BackgroundWorker1.CancellationPending = Ture Then
                    e.Cancel = True
                    '取消BackgroundWorker執行中的工作

    Else

        做要回圈執行的動作
     End If

     

     

    2008年4月17日 上午 08:08
  • Hi,

    當對backgroundworker作cancel的動作後,會把旗標設定起來,實際上的停止與離開的動作要自己手動去處理,所以如果有次數很多的迴圈又有中斷的需求的話要另外加判斷,像是

    If BackgroundWorker1.CancellationPending = Ture Then
                    e.Cancel = True
                    '取消BackgroundWorker執行中的工作

    Else

        For i as integer=0 to 100

                 If BackgroundWorker1.CancellationPending = Ture Then
                         e.Cancel = True
                         '取消BackgroundWorker執行中的工作

                         Exit For

                  END If

        Next

     End If

     

    不然還是要等到迴圈結束才會停止

    2008年4月17日 上午 09:33
    版主
  • HI,

     

    您還要加一個結束迴圈的動作, 例如Exit Do, Exit For, 或Exit While, 例如:

     

    If BackgroundWorker1.CancellationPending = Ture Then
                    e.Cancel = True
                    '取消BackgroundWorker執行中的工作

                    Exit For

    Else

        做要回圈執行的動作
     End If

     

    tihs

    2008年4月19日 上午 03:18