开发者

C# BackGroundWorker with ProgressBar Updates after process complete

I have the following in a button click event:

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

}

My 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");
      }
    }

  }

}

My Cancel Button:

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

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

My backgroundWorker1_ProgressChanged:

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

I get following output in my debug window when I processed 2 items:

backgroundWorker1_dowork=0

backgroundWorker1_dowork=0

progressbar1.value=1

progressbar1.value=2

The event is firing, but as you can see from the console.write, it's happening AFTER the thread finishes. I get the progressbar scrolling, but only once the dowork has completed.

What have I done wrong on this? I'd like it to update as each item is completed.


It's due to the way threads work. ProgressChange is invoked on the UI thread using BeginInvoke, and therefore on another thread. Meanwhile, the worker thread continues running. Since there is not much work to do, the BackgroundWorker finishes its work before BeginInvoke actually invokes the method, because thread switches don't happen every CPU operation. They happen after quite a few. To avoid this, manually call the method that increments the ProgressBar's value using this.Invoke().

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜