0

我有一个后台工作人员,它在一个单独的类中调用一个函数。可能需要随时通过从前端单击按钮来取消此过程。我试过使用 CancelAsync() 但这没有效果。cofunds_downloadfiles 是我正在调用的函数。我如何去取消这个过程?

TIA。

Private Sub btnProcessdld_Click(sender As System.Object, e As System.EventArgs) Handles btnProcessdld.Click

    Dim cfHelper As New CoFundsHelper

    If btnProcessdld.Text = "Process" Then
        btnProcessdld.Text = "Cancel"

        If chkDailyFiles.Checked = False And chkWeeklyFiles.Checked = False Then
            MessageBox.Show("Please select which files you want to download")
        Else

            lblProgress.Text = "Processing...if you are downloading weekly files this may take a few minutes"
            uaWaitdld.AnimationEnabled = True
            uaWaitdld.AnimationSpeed = 50
            uaWaitdld.MarqueeAnimationStyle = MarqueeAnimationStyle.Continuous
            uaWaitdld.MarqueeMarkerWidth = 60

            _backGroundWorkerdld = New BackgroundWorker
            _backGroundWorkerdld.WorkerSupportsCancellation = True
            _backGroundWorkerdld.RunWorkerAsync()

        End If

    ElseIf btnProcessdld.Text = "Cancel" Then
        btnProcessdld.Text = "Process"
        _backGroundWorkerdld.CancelAsync()
        uaWaitdld.AnimationEnabled = False

    End If

Private Sub StartProcessdld(ByVal sender As Object, _
    ByVal e As System.ComponentModel.DoWorkEventArgs) Handles _backGroundWorkerdld.DoWork

    Dim cfHelper As New CoFundsHelper
    cfHelper.ConnString = PremiumConnectionString
    Dim dateValue As String

    Dim weekly As Boolean = False
    Dim daily As Boolean = False

    If dtePicker.Value IsNot Nothing Then
        dateValue = Format(dtePicker.Value, "yyyyMMdd")

        If chkWeeklyFiles.Checked = True Then
            weekly = True
        End If
        If chkDailyFiles.Checked = True Then
            daily = True
        End If

        cfHelper.Cofunds_DownloadFiles(dateValue, weekly, daily)

    Else
        Throw (New Exception("Date Field is empty"))
    End If
End Sub
4

2 回答 2

1

基本上你可以做到以下几点:

  • 在 DoWork 子中,测试cancellationpending属性
  • 如果它是真的,那么你根本不调用那个函数,也许把e.Cancelled = true它放在 RunWorkerCompleted 中检查并决定你必须做什么。
  • 如果您需要取消它,只需Stop()在您的班级中创建一个完全执行此操作的子程序 - 停止该过程。然后,您只需要像这样调用它

    Me.Invoke(Sub()
              myClass.Stop()
           End Sub)
    
  • 您可能需要暂停后台工作人员,直到来自主线程的调用返回。你可以使用信号量来做到这一点: Private chk As New Semaphore(1,1,"checking1") 你把它作为一个全局变量来给你的主线程和后台工作线程。

  • 在 backgroundworker_doWork 中,您可以在chk.WaitOne()需要执行的行之后使用信号量。
  • 在你的类的方法中,当它完成计算时你放a.Release

仅当您需要确保等待结果时才需要信号量。它有点违背了多线程的目的,但是您可以在等待主线程之前在工作线程中执行其他操作(例如用其他东西启动另一个线程等)。

除此之外,调用停止方法就足够了。对不起,我没有时间分析你的代码,但我希望我能把你引向正确的方向。

于 2012-06-29T17:28:33.487 回答
1

CancelAsync实际上并没有取消工作人员(只是 sets CancellationPending = True)所以你基本上必须在你的函数中检查 BackGroundWorker 的状态:

Do While Not worker.CancellationPending
    'some long running process
Loop

但是我发现这不是 100% 可靠的,因此使用您自己的取消标志可能更安全。

于 2012-06-29T14:17:47.273 回答