【问题标题】:Backgroundworker ReportProgress event does not fireBackgroundworker ReportProgress 事件不会触发
【发布时间】:2012-10-16 14:42:26
【问题描述】:

我有一个后台工作人员,负责处理我的应用程序中的计时器。这是代码:

    protected override void OnLoad(EventArgs e)
    {
        // Inizializzo il backgroundworker 
        bgwTimer.WorkerReportsProgress = true;
        bgwTimer.WorkerSupportsCancellation = true;
        bgwTimer.DoWork += (bgwTimer_DoWork);
        bgwTimer.RunWorkerCompleted +=(bgwTimer_RunWorkerCompleted);
        bgwTimer.ProgressChanged += (bgwTimer_ProgressChanged);
    }

    void bgwTimer_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

    void bgwTimer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        throw new NotImplementedException();
    }

基本上,“ProgressChanged”事件永远不会被触发,因此我无法更新进度条的状态。 事件 DoWork 与此方法相关联:

    void bgwTimer_DoWork(object sender, DoWorkEventArgs e)
    {
        int i = 0;
        if (bgwTimer.CancellationPending)
        {
            e.Cancel = true;
        }
        else
        {
            while (bgwTimer.IsBusy)
            {                
                Thread.Sleep(1000);
                bgwTimer.ReportProgress(i);
                refreshTimer();
            }
        }
    }

在我这边,代码看起来不错,运行良好。如您所见,调用了 ReportProgress 方法,但未触发事件。有什么提示吗?

更新: 哎呀!我发现只有在事件声明后立即运行 RunWorkerAsync 时才会触发事件“bgwTimer_ProgressChanged”。基本上:

bgwTimer.ProgressChanged += (bgwTimer_ProgressChanged); bgwTimer.RunWorkerAsync(); //这行得通!

由于我在用户按下按钮时运行工作程序,因此不会触发事件。


点击事件按钮的代码如下:

    private void btnNext_Click(object sender, EventArgs e)
    {            
        this.TopMost = true;
        btnNext.Enabled = false;
        progressBar1.Step = 0;

        if (_bgwTimer.IsBusy)
            _bgwTimer.CancelAsync();
        else
            _bgwTimer.RunWorkerAsync();
    }

【问题讨论】:

  • 你没有增加 i 的值 - 也许这就是没有引发事件的原因?
  • 一个可能有帮助的参考资料(虽然我找不到你的问题)在这里:albahari.com/threading/part3.aspx#_BackgroundWorker
  • 罗伯特,定时器基本上是更新一个标签的Text属性,没有别的。
  • 这可能是个问题。根据我发布的链接,您只应该更新 BGW 不在的某些线程中的 UI 元素,因此首先是 ProgressChanged 事件,这有助于解决这个问题。我想知道这种行为是否会导致其他“有趣”的行为?
  • 在您的编辑中,您说使用按钮触发它时它不起作用。你睡眠处理按钮点击事件的线程吗?如果是这样,你已经暂停了 UI 线程(坏的),没有其他东西可以通过。哎呀,您的“完成”方法bgwTimer_RunWorkerCompleted 也不会运行。请发布您原来的“按钮点击事件”方法。我认为这将揭示根本原因。

标签: c# multithreading timer progress-bar backgroundworker


【解决方案1】:

bgwTimer.ReportProgress(i) 之前放置一个断点或Debug.PrintSystem.Windows.Forms.Messagebox,以验证您是否确实进入了while 循环。

注意BackgroundWorker 实际上并不是一个计时器;它是为您的用户界面提供线程安全调用层的线程的包装器。

您的if (bgwTimer.CancellationPending) { } 应该在while 循环内,而不是在它之外。它只会在您当前的代码中被检查一次。

请注意,如果您在 DoWork 事件处理程序中,那么根据定义,您正在运行一个异步进程,因此 IsBusy 应该始终为真(根据 MSDN 文档),因此您的 @987654330 @ 是一个无限循环。但是用你的调试器检查一下。

【讨论】:

    【解决方案2】:

    它没有引发事件,因为 i 的值始终为零,这很有帮助,但我在不久前构建后台工作人员时发现了同样的事情。

    【讨论】:

    • 哎呀!我已经添加了“i”变量的增加,但是没有触发事件
    【解决方案3】:

    您忘记启动工作程序。将此行添加到您的 OnLoad() 方法中:

       bgwTimer.RunWorkerAsync();
    

    【讨论】:

    • +1 进行了很好的观察,实际上它被省略了,这只能让您假设工人甚至从未启动过。
    • 对不起,我在发布的代码中省略了这一行,但我已经在我的代码中。当用户按下按钮时,我会触发 RunWorker。
    • 因此,您没有发布与此问题相关的重要代码。我们不能从这里越过你的肩膀。
    【解决方案4】:

    在 DoWork-Method 中通过 ((BackgroundWorker)sender) 替换 bgwTimer。也许这就是问题

    【讨论】:

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