首页 文章

停止然后快速连续启动相同的后台工作程序

提问于
浏览
1

当在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

2 回答

  • 1

    而不是检查 IsBusy ,我会处理 BackgroundWorker.RunWorkerCompleted event

    在后台操作完成,已取消或引发异常时发生 .

    并推迟重新启动worker到此事件的处理程序 .

  • 3

    这种方法怎么样?...我们只需用新的替换旧的背景工作者:

    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
    

相关问题