vb.net 后台工作程序 CancelAsync() 不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16893953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Backgroundworker CancelAsync() won't work
提问by Ponch0
I am trying to cancel my Backgroundworker with WorkerClass.bw.CancelAsync(). But it wont work at all.
我正在尝试使用WorkerClass.bw.CancelAsync(). 但它根本不起作用。
//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 falsewhile the worker is doing things!?!?
//编辑!我在这里发布了完整的代码。愿这会有所帮助。好的,我添加了一些 Msgboxes 来知道 Worker 是否仍然很忙,而有线的事情是,我有一段false时间 Worker 正在做事!?!?
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_fwor
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
采纳答案by mclark1129
I think your problem is that you are only evaluating CancellationPendingonce, at the start of your bw_DoWorkmethod. Since there's not really a way to cancel the BackgroundWorkerbefore it starts, CancellationPendingwill 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.
我认为你的问题是你只CancellationPending在你的bw_DoWork方法开始时评估一次。由于没有真正的方法可以BackgroundWorker在它开始之前取消,CancellationPending将始终为假并且永远不会中断工作。当您调用 .BackgroundWorker 时,BackgroundWorker 不会使用一些魔法来接管程序计数器CancelAsync。
In order for this to work, the core logic of your DoWorkmethod will have to be implemented in a way that allows for the frequent polling of CancellationPendingso that the code will know exactly when to exit out of what it's doing. You will need to go from this:
为了使其工作,您的DoWork方法的核心逻辑必须以允许频繁轮询的方式实现,CancellationPending以便代码准确知道何时退出正在执行的操作。你需要从这里开始:
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
回答by dbasnett
Here is the basic model of a BackgroundWorker. Is this how yours look.
这是 BackgroundWorker 的基本模型。这是你的样子吗。
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

