如何取消后台工作者调用的函数?

时间:2012-06-29 14:10:50

标签: vb.net backgroundworker

我有一个后台工作程序,它在一个单独的类中调用一个函数。可以通过从前端点击按钮随时取消此过程。我尝试过使用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

2 个答案:

答案 0 :(得分:1)

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

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

我发现这不是100%可靠,所以使用你自己的取消标志可能更安全。

答案 1 :(得分: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

只有在需要确保等待结果时才需要信号量。它有点违背多线程的目的但你可以在等待主线程之前在worker中执行其他操作(比如用其他东西开始另一个线程等)。

除了调用stop方法应该就足够了。很抱歉,我没有时间分析您的代码,但我希望我能让您朝着正确的方向前进。