C# BackGroundWorker 与 ProgressBar 流程完成后更新

标签 c# progress-bar backgroundworker

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

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 中看到的那样,它是在线程完成后发生的。我得到进度条滚动,但只有在 dowork 完成后。

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

最佳答案

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

关于C# BackGroundWorker 与 ProgressBar 流程完成后更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5710784/

相关文章:

c# - GetResponse() 发生 500 内部服务器错误

c# - 如何从它绑定(bind)到的 DataRow 中确定 DataGridViewRow

r - 使用 doParallel + foreach 显示 progress_bar

c# - .NET 4.0 TPL 不是让 APM、EAP 和 BackgroundWorker 异步模式过时了吗?

c# - 是否可以在同一解决方案中使用带有单独类库的后台 worker

c# - 从 WPF 中的后台 worker 更新进度条

c# - IronPdf 打印到页边距

c# - WPF DataGridRow ContextMenu MenuItem 单击事件未触发

android - ProgressDrawable 图层列表的图像应该是什么样的?

html - CSS 进度条