【问题标题】:C# BackGroundWorker with ProgressBar Updates after process complete进程完成后带有 ProgressBar 更新的 C# BackGroundWorker
【发布时间】:2023-03-05 21:09:01
【问题描述】:

我在按钮点击事件中有以下内容:

private void buttonSubmitAchChecks_Click(object sender, EventArgs e)
{
  if (backgroundWorker1.IsBusy) return;
  SubmittingAch(true);

  backgroundWorker1.WorkerReportsProgress = true;
  backgroundWorker1.WorkerSupportsCancellation = true;

  label_Status.Text = "Submitting checks to ACH ....";
  var qry = from ds in checkTrans.IndividualCheck
            where ds.SubmitToACH &&
                  ds.Status == "Entered" &&
                  ds.CheckAmount > 0 &&
                  ds.SubmitToACH
            select ds;

  if (qry.Count() <= 0)
  {
    label_Status.Text = "Nothing to submit. Check the Check Amount, ACH, and Status fields.";
  }
  else
  {
    progressBar1.Maximum = qry.Count();
    progressBar1.Minimum = 0;
    progressBar1.Step = 1;
    backgroundWorker1.RunWorkerAsync(qry);
  }

}

我的 backgroundWorker1_DoWork:

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
  if (backgroundWorker1.CancellationPending)
  {
    e.Cancel = true;
  }
  else
  {
    var qry = e.Argument as EnumerableRowCollection<CheckTrans.IndividualCheckRow>;
    if (qry != null)
    {
      Thread.Sleep(4000);

      //item.Status = ach.SubmitCheck(item);
      var ach = new SubmitAchChecks();
      foreach (var item in qry)
      {
        ach.SubmitCheck(item);
        backgroundWorker1.ReportProgress(1);
        Console.Write("backgroundWorker1_dowork=" + progressBar1.Value.ToString() + "\r\n");
      }
    }

  }

}

我的取消按钮:

private void cancelAsyncButton_Click(object sender, EventArgs e)
{
  if (backgroundWorker1.WorkerSupportsCancellation == true)
  {
    label_Status.Text = "Cancelling...";
    backgroundWorker1.CancelAsync();
  }
}

我的 backgroundWorker1_RunWorkerCompleted:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  if (e.Cancelled == true)
  {
    label_Status.Text = "Canceled!";
  }
  else if (e.Error != null)
  {
    label_Status.Text = "Error: " + e.Error.Message;
  }
  else
  {
    label_Status.Text = "Done!";
  }
  SubmittingAch(false);
}

我的 backgroundWorker1_ProgressChanged:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
  progressBar1.Value += 1;
  Console.Write("progressbar1.value=" + progressBar1.Value.ToString() + "\r\n");
}

当我处理 2 个项目时,我在调试窗口中得到以下输出:

backgroundWorker1_dowork=0

backgroundWorker1_dowork=0

progressbar1.value=1

progressbar1.value=2

事件正在触发,但正如您从 console.write 中看到的那样,它发生在线程完成之后。我让进度条滚动,但只有在工作完成后才能滚动。

我在这方面做错了什么?我希望它在每个项目完成后更新。

【问题讨论】:

  • 这与您的实际问题无关,但我注意到您在 LINQ 结果qry 中检查了两次ds.SubmitToACH

标签: c# progress-bar backgroundworker


【解决方案1】:

这是由于线程的工作方式。 ProgressChange 在 UI 线程上使用 BeginInvoke 调用,因此在另一个线程上调用。同时,工作线程继续运行。由于没有太多工作要做,BackgroundWorkerBeginInvoke 实际调用该方法之前完成了它的工作,因为线程切换不会发生在每个 CPU 操作中。它们发生在很多次之后。为避免这种情况,请手动调用使用this.Invoke() 递增ProgressBar 值的方法。

【讨论】:

  • 这就是我需要的!谢谢!对于那些搜索,这里是微软网站上调用的链接,我在其中使用了他们的示例,它运行良好:msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
  • 尝试了这个以及我在这里找到的几乎所有答案,但仍然没有乐趣。我的进度条会一直等到工作线程完成,然后再繁荣——它会更新。
  • @Bertie:这有两个可能的原因:UI 线程也在工作,或者没有报告进度。您可以通过尝试与 UI 交互来区分两者。当您期望进度条移动时,表单上的其他按钮是否响应?窗口控件?一旦你弄清楚了,下一步就是使用调试器:在后一种情况下,在进度报告上断点,在工作期间暂停以找出主线程在前一种情况下正在做什么。
  • @Ry- 经过大量的调整 - 基本上按照您的建议进行操作,我仍然得到相同的结果。正在报告进度,按钮和窗口控件响应,调试证明一切 wws 在那里被调用。现在,我将我的逻辑放在了 DoWork 的单独方法中。作为最后的手段,我将代码剪切并粘贴到 DoWork 方法中,编译,运行......鲍勃是你的叔叔,它应该更新。我把它移回了它自己的方法,它又停止了工作。基本上,代码必须在 DoWork 方法中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多