我正在尝试使用
WorkerClass.bw.CancelAsync()
取消我的后台工作人员。但这根本行不通。
//编辑!我在这里发布了完整的代码。希望这会有所帮助。 好的,我添加了一些消息框来了解工作人员是否仍然忙碌,并且有线的事情是,当工作人员正在做事时我会收到
false
!?!?
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
我认为你的问题是你只在
CancellationPending
方法开始时评估 bw_DoWork
一次。由于实际上没有办法在开始之前取消 BackgroundWorker
,因此 CancellationPending
将始终为 false,并且永远不会中断工作。当您调用 CancelAsync
时,BackgroundWorker 不会使用某种魔法来接管程序计数器。
为了使其发挥作用,
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
对于类似这样的事情:
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
这是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
创建: 1 个名为“frmMain”的表单,
含 1 个名为“Button1”的按钮, 1 x 进度条,名为“ProgressBar1”。
然后将此代码粘贴到:
Imports System.ComponentModel
Public Class frmMain
' Create a BackgroundWorker instance
Private WithEvents backgroundWorker1 As New System.ComponentModel.BackgroundWorker()
Public Sub New()
InitializeComponent()
' Configure the BackgroundWorker
backgroundWorker1.WorkerReportsProgress = True
backgroundWorker1.WorkerSupportsCancellation = True
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Set the ProgressBar properties
progressBar1.Minimum = 0
progressBar1.Maximum = 100
progressBar1.Value = 0
End Sub
' Event handler for the Start button click
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Cancel the BackgroundWorker if it's running
If backgroundWorker1.IsBusy Then
backgroundWorker1.CancelAsync()
Button1.Text = "Start"
Else
backgroundWorker1.RunWorkerAsync()
Button1.Text = "Cancel"
End If
End Sub
' Event handler for the BackgroundWorker's DoWork event
Private Sub backgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles backgroundWorker1.DoWork
For i As Integer = 0 To 100
' Check if cancellation is requested
If backgroundWorker1.CancellationPending Then
e.Cancel = True
Exit For
End If
' Simulate work by sleeping for a short duration
System.Threading.Thread.Sleep(10)
' Report progress to the UI thread
backgroundWorker1.ReportProgress(i)
Next
End Sub
' Event handler for the BackgroundWorker's ProgressChanged event
Private Sub backgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles backgroundWorker1.ProgressChanged
' Update the ProgressBar value based on the reported progress
progressBar1.Value = e.ProgressPercentage
End Sub
' Event handler for the BackgroundWorker's RunWorkerCompleted event
Private Sub backgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles backgroundWorker1.RunWorkerCompleted
' Perform any cleanup or post-processing after the backgroundWorker has either finished, or aborted
If ProgressBar1.Value = 100 Then
MessageBox.Show("Progress completed!")
Else
MessageBox.Show("Operation Aborted!")
ProgressBar1.Value = 0
End If
End Sub
End Class