【问题标题】:Cannot Await BackgroundWorker CancelAsync无法等待 BackgroundWorker CancelAsync
【发布时间】:2018-04-21 07:35:34
【问题描述】:

我的项目中有一个 BackgroundWorker,我想用一个方法重新启动它。但是,当我使用CancelAsync() 方法,然后立即使用RunWorkerAsync() 方法时,取消尚未完成,BackgroundWorker 的 2 个实例已启动并引发 InvalidOperationException。为了解决这个问题,我使方法异步(它是一个 Sub 方法)并等待 CancelAsync() 等待它完成。但是,这会返回表达式不产生值的错误。是调用还是worker的方法造成的?

工人方法:

Private Sub GIFworker(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bkwGIF.DoWork
        Dim hum As Integer = e.Argument
        If hum Mod 2 = 1 Then
            While bkwGIF.CancellationPending = False
                pbxRpsHum.Image = ilRPS.Images(0)
                Thread.Sleep(1000)
                pbxRpsHum.Image = ilRPS.Images(1)
                Thread.Sleep(1000)
            End While
        Else
            While bkwGIF.CancellationPending = False
                pbxRpsHum.Image = ilRPS.Images(0)
                Thread.Sleep(1000)
                pbxRpsHum.Image = ilRPS.Images(3)
                Thread.Sleep(1000)
            End While
        End If
    End Sub

调用CancelAsync()(哼是整数):

Await bkwGIF.CancelAsync()
bkwGIF.RunWorkerAsync(hum)

【问题讨论】:

  • BackgroundWorker 仍将控制权传递给 RunworkerCompleted 事件。将 Cancelled 的结果设置为 0 之类的值,然后在 RunWorkerCompleted 事件中检查结果并从那里重新启动 backgroundworker。
  • 您需要阅读BackgroundWorker 课程。 CancelAsync 不可等待。它是旧异步模式的一部分。
  • @F0r3v3r-A-N00b,这不是这样做的方法。如果您在DoWork 事件处理程序中检测到CancellationPendingTrue,并且您确实取消了工作,则应该将e.Cancel 设置为True。然后您可以在RunWorkerCompleted 事件处理程序中检查e.Cancelled,它也将是True
  • 哦,好的。不知道 e.Cancelled 部分。谢谢

标签: vb.net winforms async-await backgroundworker


【解决方案1】:

以下是如何取消BackgroundWorker 的示例:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    'Raise the DoWork event in a worker thread.
    Me.BackgroundWorker1.RunWorkerAsync()
End Sub

'This method is executed in a worker thread.
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim worker As BackgroundWorker = DirectCast(sender, BackgroundWorker)

    For i As Integer = 1 To 100
        If worker.CancellationPending Then
            'The user has cancelled the background operation.
            e.Cancel = True
            Exit For
        End If

        'Raise the ProgressChanged event in the UI thread.
        worker.ReportProgress(i, i & " iterations complete")

        'Perform some time-consuming operation here.
        Threading.Thread.Sleep(250)
    Next i
End Sub

'This method is executed in the UI thread.
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    Me.ProgressBar1.Value = e.ProgressPercentage
    Me.Label1.Text = TryCast(e.UserState, String)
End Sub

'This method is executed in the UI thread.
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    If e.Cancelled Then
        'The background operation was cancelled.
        Me.Label1.Text = "Operation cancelled"
    Else
        'The background operation completed normally.
        Me.Label1.Text = "Operation complete"
    End If
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    'Only cancel the background opertion if there is a background operation in progress.
    If Me.BackgroundWorker1.IsBusy Then
        Me.BackgroundWorker1.CancelAsync()
    End If
End Sub

如果您想在取消时重新启动后台工作,那么当您检测到e.CancelledTrue 时,您可以在RunWorkerCompleted 事件处理程序中执行此操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    相关资源
    最近更新 更多