Vb.net 快速连续停止然后启动同一后台工作程序
在CancelAsync()调用和RunWorkerAsync()调用之间只有很小的间隔时,我很难使用VB.net停止然后启动后台工作程序。我创建了一个示例来说明下面的问题。如果快速连续单击按钮一次,然后单击两次,则会出现此示例中的问题。基本上,据我所知,问题在于后台工作程序仍在迭代for循环(包括模拟运行需要一些时间的代码),并且还没有机会检查取消是否挂起 我尝试使用的解决方案是等待后台工作程序关闭,然后再次启动该工作程序。然而,这个while循环无限期地迭代——后台工作进程永远不会终止。我假设将主线程置于睡眠状态也会使后台工作线程处于睡眠状态。这是正确的吗 问题:当无法合理地经常检查挂起的取消时,建议如何停止后台工作人员,然后可能需要在几分之一秒后再次启动它 非常感谢您的建议和评论Vb.net 快速连续停止然后启动同一后台工作程序,vb.net,backgroundworker,background-process,Vb.net,Backgroundworker,Background Process,在CancelAsync()调用和RunWorkerAsync()调用之间只有很小的间隔时,我很难使用VB.net停止然后启动后台工作程序。我创建了一个示例来说明下面的问题。如果快速连续单击按钮一次,然后单击两次,则会出现此示例中的问题。基本上,据我所知,问题在于后台工作程序仍在迭代for循环(包括模拟运行需要一些时间的代码),并且还没有机会检查取消是否挂起 我尝试使用的解决方案是等待后台工作程序关闭,然后再次启动该工作程序。然而,这个while循环无限期地迭代——后台工作进程永远不会终止。我假
Public Class Form1
Dim WithEvents bgWorker As System.ComponentModel.BackgroundWorker = New System.ComponentModel.BackgroundWorker
Friend WithEvents startStopButton As Button = New Button
Dim workerShouldBeRunning As Boolean = False
Sub startStopButton_click() Handles startStopButton.Click
If workerShouldBeRunning Then
bgWorker.CancelAsync()
Else
While bgWorker.IsBusy
Threading.Thread.Sleep(1)
End While
bgWorker.RunWorkerAsync()
End If
workerShouldBeRunning = Not workerShouldBeRunning
End Sub
Sub bgWorker_doWork() Handles bgWorker.DoWork
While Not bgWorker.CancellationPending
Dim sum As Long
For counter = 1 To 100000
sum += counter
Next
Threading.Thread.Sleep(1000)
End While
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
startStopButton.Location = New Point(10, 100)
startStopButton.Size = New System.Drawing.Size(200, 23)
startStopButton.Text = "Click" 'Click to start or stop the background dummy process.
Me.Controls.Add(startStopButton)
bgWorker.WorkerSupportsCancellation = True
End Sub
End Class
编辑:
根据Ross Presser的建议,我改进了示例代码。不过,解决方案似乎有点糟糕
Public Class Form1
Dim WithEvents bgWorker As System.ComponentModel.BackgroundWorker = New System.ComponentModel.BackgroundWorker
Friend WithEvents startStopButton As Button = New Button
Dim workerShouldBeRunning As Boolean = False
Dim startQueued As Boolean = False
Sub startStopButton_click() Handles startStopButton.Click
If workerShouldBeRunning Then
bgWorker.CancelAsync()
Else
If bgWorker.IsBusy Then
startQueued = True
Else
bgWorker.RunWorkerAsync()
End If
End If
workerShouldBeRunning = Not workerShouldBeRunning
End Sub
Sub bgWorker_doWork() Handles bgWorker.DoWork
While Not bgWorker.CancellationPending
Dim sum As Long
For counter = 1 To 100000
sum += counter
Next
Threading.Thread.Sleep(1000)
End While
End Sub
Sub bgWorkerCompleted() Handles bgWorker.RunWorkerCompleted
If startQueued Then
startQueued = False
bgWorker.RunWorkerAsync()
End If
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
startStopButton.Location = New Point(10, 100)
startStopButton.Size = New System.Drawing.Size(200, 23)
startStopButton.Text = "Click" 'Click to start or stop the background dummy process.
Me.Controls.Add(startStopButton)
bgWorker.WorkerSupportsCancellation = True
End Sub
End Class
我将处理
BackgroundWorker.RunWorkerCompleted
在后台操作已完成、已取消或引发异常时发生
并将此事件的重新启动工作进程推迟到处理程序。我将处理
BackgroundWorker.RunWorkerCompleted
而不是检查IsBusy
在后台操作已完成、已取消或引发异常时发生
并将此事件的重新启动工作进程推迟到处理程序。这种方法如何?…我们只需将旧的backgroundworker替换为新的backgroundworker:
Public Class Form1
Private WithEvents startStopButton As Button = New Button
Private WithEvents bgWorker As System.ComponentModel.BackgroundWorker = Nothing
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
startStopButton.Location = New Point(10, 100)
startStopButton.Size = New System.Drawing.Size(200, 23)
startStopButton.Text = "Click" 'Click to start or stop the background dummy process.
Me.Controls.Add(startStopButton)
End Sub
Private Sub startStopButton_click() Handles startStopButton.Click
If IsNothing(bgWorker) Then
Static bgwCounter As Integer = 0
bgwCounter = bgwCounter + 1
bgWorker = New System.ComponentModel.BackgroundWorker
bgWorker.WorkerSupportsCancellation = True
bgWorker.RunWorkerAsync(bgwCounter)
Else
bgWorker.CancelAsync()
bgWorker = Nothing
End If
End Sub
Private Sub bgWorker_doWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgWorker.DoWork
Dim bgwCounter As Integer = e.Argument
Debug.Print("Running #" & bgwCounter)
Dim bgw As System.ComponentModel.BackgroundWorker = sender
While Not bgw.CancellationPending
Dim sum As Long
For counter As Integer = 1 To 100000
sum += counter
Next
Threading.Thread.Sleep(1000)
End While
Debug.Print("Cancelled #" & bgwCounter)
End Sub
End Class
这种方法怎么样?…我们只是用新的backgroundworker替换旧的backgroundworker:
Public Class Form1
Private WithEvents startStopButton As Button = New Button
Private WithEvents bgWorker As System.ComponentModel.BackgroundWorker = Nothing
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
startStopButton.Location = New Point(10, 100)
startStopButton.Size = New System.Drawing.Size(200, 23)
startStopButton.Text = "Click" 'Click to start or stop the background dummy process.
Me.Controls.Add(startStopButton)
End Sub
Private Sub startStopButton_click() Handles startStopButton.Click
If IsNothing(bgWorker) Then
Static bgwCounter As Integer = 0
bgwCounter = bgwCounter + 1
bgWorker = New System.ComponentModel.BackgroundWorker
bgWorker.WorkerSupportsCancellation = True
bgWorker.RunWorkerAsync(bgwCounter)
Else
bgWorker.CancelAsync()
bgWorker = Nothing
End If
End Sub
Private Sub bgWorker_doWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgWorker.DoWork
Dim bgwCounter As Integer = e.Argument
Debug.Print("Running #" & bgwCounter)
Dim bgw As System.ComponentModel.BackgroundWorker = sender
While Not bgw.CancellationPending
Dim sum As Long
For counter As Integer = 1 To 100000
sum += counter
Next
Threading.Thread.Sleep(1000)
End While
Debug.Print("Cancelled #" & bgwCounter)
End Sub
End Class
谢谢你的回复。然而,我认为这并不能解决问题。后台进程不一定需要立即重新启动,只是它有可能立即重新启动(如果这是用户选择的)。(编辑窗口丢失。)也就是说,如果用户需要,程序只需重新启动后台工作程序,在本例中,通过单击按钮表示。感谢您的回复。然而,我认为这并不能解决问题。后台进程不一定需要立即重新启动,只是它有可能立即重新启动(如果这是用户选择的)。(编辑窗口丢失。)也就是说,如果用户需要,程序只需重新启动后台工作程序,在本例中,单击按钮表示。如果BackgroundWorker当前正在运行,则在单击“取消”时禁用该按钮。在RunWorkerCompleted()事件中重新启用它。@idle mind感谢您的评论。我相信这更像是一种解决方法,而不是修复方法,但我认为我暂时可以解决这个问题。您正在尝试在按钮单击处理程序中“保留”代码,直到发生其他事件。这是一个不,不…@懒惰的想法我同意我试图使用比你更糟糕的解决方法。禁用按钮,虽然可能会让用户感到困惑,但要好得多。如果BackgroundWorker当前正在运行,则在单击“取消”时禁用按钮。在RunWorkerCompleted()事件中重新启用它。@idle mind感谢您的评论。我相信这更像是一种解决方法,而不是修复方法,但我认为我暂时可以解决这个问题。您正在尝试在按钮单击处理程序中“保留”代码,直到发生其他事件。这是一个不,不…@懒惰的想法我同意我试图使用比你更糟糕的解决方法。禁用按钮,虽然可能会让用户感到困惑,但要好得多。谢谢。这是一个很好的答案,它很好地解决了问题。谢谢。这是一个很好的答案,它很好地解决了问题。