【问题标题】:How do I properly cancel and restart a BackgroundWorker process?如何正确取消并重新启动 BackgroundWorker 进程?
【发布时间】:2010-10-12 17:14:43
【问题描述】:

我的应用程序的用户将 HTML 类型输入到 TextBox 控件中。

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

因为我不想锤击验证服务,所以我尝试在每次验证之前建立一秒延迟。

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

我的 Visual Basic 代码:

子 W3CValidate(ByVal WholeDocumentText 作为字符串) '停止任何已经运行的验证 If ValidationWorker.IsBusy Then ValidationWorker.CancelAsync() '等待它准备好 While ValidationWorker.IsBusy '暂停百分之一秒 System.Threading.Thread.Sleep(新时间跨度(0、0、0、0、10)) 结束时 万一 '开始验证 Dim ValidationArgument As W3CValidator = New W3CValidator(WholeDocumentText) ValidationWorker.RunWorkerAsync(ValidationArgument) 结束子

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

我做错了什么?

【问题讨论】:

  • 我的意思是如果 e.Cancelled 为真则退出程序。

标签: .net multithreading backgroundworker


【解决方案1】:

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

BackgroundWorker Closure and Overridable Task帕特里克·斯马基亚

我已经修改了他的代码:

私有 _ValidationArgument 作为 W3CValidator 子 W3CValidate(ByVal WholeDocumentText 作为字符串) If _ValidationArgument IsNot Nothing Then _ValidationArgument = 新的 W3CValidator(WholeDocumentText) 退出子 万一 If Not ValidationWorker.IsBusy Then ValidationWorker.RunWorkerAsync(新 W3CValidator(WholeDocumentText)) 退出子 万一 _ValidationArgument = 新的 W3CValidator(WholeDocumentText) ValidationWorker.CancelAsync() 昏暗 TimerRetryUntilWorkerNotBusy 作为新的 Windows.Threading.DispatcherTimer AddHandler TimerRetryUntilWorkerNotBusy.Tick, AddressOf WorkTicker TimerRetryUntilWorkerNotBusy.Interval = New TimeSpan(1) '100 纳秒 TimerRetryUntilWorkerNotBusy.Start() 结束子 Sub WorkTicker(ByVal sender As Object, ByVal e As System.EventArgs) If ValidationWorker.IsBusy Then 退出子 万一 DirectCast(sender, Windows.Threading.DispatcherTimer).Stop() ValidationWorker.RunWorkerAsync(_ValidationArgument) _ValidationArgument = 无 结束子

【讨论】:

    【解决方案2】:

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

    更新:设置 Cancel = true 后,您是否退出该方法? 在这里吐口水 更新 2:您在后台工作人员上将 WorkerSupportsCancellation 标志设置为 true? 如果 e.Cancelled.... 更多 spitballs

    更新 3: 经过我自己的一些检查和编译后,这该死的东西似乎永远不会在同一个方法中脱离 isbusy 。 - 一个选项是在忙碌时禁用该按钮并让另一个选项取消,只供用户重新单击验证。 - 或者在您的工作人员完成的方法上,如果(e.Cancelled)使用适当的文本调用您的验证方法....

    不过,无论哪种方式都有些失败。很抱歉在这里帮不上什么忙。

    【讨论】:

    • 这也是我的预期。如果 DirectCast(sender, BackgroundWorker).CancellationPending,我的 DoWork() 方法确实设置了 e.Cancel = True。但无论如何,IsBusy 从未返回 False。
    • My DoWork() 运行“e.Cancel = True”,然后立即“Exit Sub”。我的 RunWorkerCompleted() 只是在 If 条件内完成所有工作:“If Not e.Cancelled Then ... End If End Sub”。必须做更多吗?
    • 是的。我设置了 ValidationWorker.WorkerSupportsCancellation = True。 “如果 e.Cancelled 则返回”是什么意思?
    【解决方案3】:

    试试这样的:

    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();
        }
    

    【讨论】:

    • 如何修改它以将新参数传递给 RunWorkerAsync?
    • 我发现这个答案对从数据库中查找建议的文本框很有帮助。要传递参数,首先使用 RunWorkerAsync(object) 并且因为 RunWorkerCompleted 也在 UI 线程中运行,所以在那里传递新值。
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 2015-11-17
    • 2013-11-08
    • 1970-01-01
    相关资源
    最近更新 更多