Backgroundworker CancelAsync() won't work

匿名 (未验证) 提交于 2019-12-03 08:52:47

问题:

I am trying to cancel my Backgroundworker with WorkerClass.bw.CancelAsync(). But it wont work at all.

//edit! I posted the full Code here. May this will help. Okay, i added some Msgboxes to know if the Worker is still busy and the wired thing is, that i get a false while the worker is doing things!?!?

Public Class Form1  Private Sub btn_start_click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_start.Click         Dim WorkerClass As New BGWClass         WorkerClass.bw.WorkerSupportsCancellation = True         WorkerClass.bw.WorkerReportsProgress = True         If btn_start.Text = "Start" Then             btn_start.Image = My.Resources.Resources.gem_remove             btn_add_addy.Enabled = False             btn_start.Text = "Stop"             WorkerClass.Start()             WorkerClass.bw.RunWorkerAsync()             MsgBox(WorkerClass.bw.IsBusy & " " & WorkerClass.bw.WorkerSupportsCancellation)         Else             btn_start.Image = My.Resources.Resources.error_fuck             btn_add_addy.Enabled = True             btn_start.Enabled = False             MsgBox(WorkerClass.bw.IsBusy & " " & WorkerClass.bw.WorkerSupportsCancellation)             WorkerClass.bw.CancelAsync()         End If     End Sub End Class  Public Class BGWClass     Public bw As BackgroundWorker = New BackgroundWorker      Sub Start()         AddHandler bw.DoWork, AddressOf bw_DoWork         AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged         AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted     End Sub      Private Sub bw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)          For x As Integer = 1 To 15             If bw.CancellationPending Then                 e.Cancel = True                 Exit Sub             End If             bw.ReportProgress(x)             Threading.Thread.Sleep(1000)         Next     End Sub      Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs)         Dim myObject As Object = e.UserState         Form1.Prgs_error.Text = "- Error: " + e.ProgressPercentage.ToString     End Sub      Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)         '...     End Sub End Class 

回答1:

I think your problem is that you are only evaluating CancellationPending once, at the start of your bw_DoWork method. Since there's not really a way to cancel the BackgroundWorker before it starts, CancellationPending will always be false and will never interrupt the work. The BackgroundWorker doesn't use some magic to take over the program counter when you call CancelAsync.

In order for this to work, the core logic of your DoWork method will have to be implemented in a way that allows for the frequent polling of CancellationPending so that the code will know exactly when to exit out of what it's doing. You will need to go from this:

Private Sub bw_DoWork(ByVal sender As Object,                        ByVal e As System.ComponentModel.DoWorkEventArgs)      If bw.CancellationPending = True Then         e.Cancel = True     Else         'do stuff here     End If  End Sub 

To something more like this:

Private Sub bw_DoWork(ByVal sender As Object,                        ByVal e As System.ComponentModel.DoWorkEventArgs)      Dim workIsCompleted As Boolean = False     While (Not bw.CancellationPending) AndAlso (Not workIsCompleted) Then          ' Do stuff here, but incrementally so that the while loop can         ' periodically check to see if CancelAsync has been called.         ' Also, be sure to set workIsCompleted = True when the work is done.         ' Otherwise, you will just spin forever until someone cancels it         ' (Which may or may not be a bad thing, depending on your requirements)      End While  End Sub 


回答2:

Here is the basic model of a BackgroundWorker. Is this how yours look.

Dim WithEvents worker As New System.ComponentModel.BackgroundWorker  Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click     'start     If Not worker.IsBusy Then         worker.WorkerReportsProgress = True         worker.WorkerSupportsCancellation = True         worker.RunWorkerAsync()     End If End Sub  Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click     'cancel     If worker.IsBusy AndAlso worker.WorkerSupportsCancellation Then         worker.CancelAsync()     End If End Sub  Private Sub foo_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles worker.DoWork     For x As Integer = 1 To 15         If worker.CancellationPending Then             e.Cancel = True             Exit For         End If         worker.ReportProgress(x)         Threading.Thread.Sleep(1000)     Next End Sub  Private Sub foo_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles worker.ProgressChanged     Label1.Text = e.ProgressPercentage.ToString End Sub  Private Sub foo_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted     If e.Cancelled Then         Label1.Text = "canceled"     ElseIf Not IsNothing(e.Error) Then         Label1.Text = "error " & e.Error.Message     Else         Label1.Text = "done"     End If End Sub 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!