如何正确取消并重新启动BackgroundWorker进程?

时间:2009-03-11 15:51:36

标签: .net multithreading backgroundworker

我的应用程序的用户将HTML键入TextBox控件。

我希望我的应用程序在后台验证他们的输入。

因为我不想敲定验证服务,所以我试图在每次验证之前建立一秒钟的延迟。

但是,我似乎无法正确中断已经运行的BackgroundWorker进程。

我的Visual Basic代码:

Sub W3CValidate(ByVal WholeDocumentText As String)

    'stop any already-running validation
    If ValidationWorker.IsBusy Then
        ValidationWorker.CancelAsync()
        'wait for it to become ready
        While ValidationWorker.IsBusy
            'pause for one-hundredth of a second
            System.Threading.Thread.Sleep(New TimeSpan(0, 0, 0, 0, 10))
        End While
    End If

    'start validation
    Dim ValidationArgument As W3CValidator = New W3CValidator(WholeDocumentText)
    ValidationWorker.RunWorkerAsync(ValidationArgument)

End Sub

似乎在调用我的BackgroundWorker的CancelAsync()之后,它的IsBusy永远不会变为False。它陷入无限循环。

我做错了什么?

3 个答案:

答案 0 :(得分:9)

尝试这样的事情:

bool restartWorker = false;

    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
                    // add other code here
        if (e.Cancelled && restartWorker)
        {
            restartWorker = false;
            backgroundWorker1.RunWorkerAsync();
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (backgroundWorker1.IsBusy)
        {
            restartWorker = true;
            backgroundWorker1.CancelAsync();
        }
        else
            backgroundWorker1.RunWorkerAsync();
    }

答案 1 :(得分:1)

在后台工作程序循环中,您需要检查
backgroundWorkerPageProcess.CancellationPending
并相应退出。然后一旦它存在你的while循环isBusy应该相应地标记。

更新:设置Cancel = true后,您是否退出方法? spitballing here 更新2:您是否在backgroundworker上将WorkerSupportsCancellation标志设置为true? 如果e.Cancelled ....更多spitballs

也在工人完成的方法返回

更新3: 在对我自己进行一些检查和编译之后,似乎该死的东西永远不会在同一方法中脱离isbusy。 - 一个选项是在忙碌时禁用该按钮并让另一个按钮取消,仅供用户重新点击验证。 - 如果(e.Cancelled)用适当的文本调用你的验证方法,你的工人完成方法....

无论哪种方式都有点破灭。很抱歉在这里没有多大帮助。

答案 2 :(得分:0)

我在这篇文章中找到了答案:

Patrick Smacchia的

BackgroundWorker Closure and Overridable Task

我改编了他的代码:

Private _ValidationArgument As W3CValidator

Sub W3CValidate(ByVal WholeDocumentText As String)
    If _ValidationArgument IsNot Nothing Then
        _ValidationArgument = New W3CValidator(WholeDocumentText)
        Exit Sub
    End If
    If Not ValidationWorker.IsBusy Then
        ValidationWorker.RunWorkerAsync(New W3CValidator(WholeDocumentText))
        Exit Sub
    End If
    _ValidationArgument = New W3CValidator(WholeDocumentText)
    ValidationWorker.CancelAsync()
    Dim TimerRetryUntilWorkerNotBusy As New Windows.Threading.DispatcherTimer
    AddHandler TimerRetryUntilWorkerNotBusy.Tick, AddressOf WorkTicker
    TimerRetryUntilWorkerNotBusy.Interval = New TimeSpan(1) '100 nanoseconds
    TimerRetryUntilWorkerNotBusy.Start()
End Sub

Sub WorkTicker(ByVal sender As Object, ByVal e As System.EventArgs)
    If ValidationWorker.IsBusy Then
        Exit Sub
    End If
    DirectCast(sender, Windows.Threading.DispatcherTimer).Stop()
    ValidationWorker.RunWorkerAsync(_ValidationArgument)
    _ValidationArgument = Nothing
End Sub