C#BackgroundWorker的进度与更新过程完成后, [英] C# BackGroundWorker with ProgressBar Updates after process complete

查看:186
本文介绍了C#BackgroundWorker的进度与更新过程完成后,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个按钮单击事件如下:

 私人无效buttonSubmitAchChecks_Click(对象发件人,EventArgs五)
{
如果(backgroundWorker1.IsBusy)回报;
SubmittingAch(真);

backgroundWorker1.WorkerReportsProgress = TRUE;
backgroundWorker1.WorkerSupportsCancellation = TRUE;

label_Status.Text =提交检查,ACH ......;
VAR QRY =从checkTrans.IndividualCheck
DS哪里ds.SubmitToACH&放大器;&安培;
ds.Status ==输入&放大器;&安培;
ds.CheckAmount> 0安培;&安培;
ds.SubmitToACH
选择DS;

如果(qry.Count()< = 0)
{
label_Status.Text =。没有提交检查支票金额,ACH,和状态字段 ;
}
,否则
{
progressBar1.Maximum = qry.Count();
progressBar1.Minimum = 0;
progressBar1.Step = 1;
backgroundWorker1.RunWorkerAsync(QRY);
}

}



我backgroundWorker1_DoWork:



 私人无效backgroundWorker1_DoWork(对象发件人,System.ComponentModel.DoWorkEventArgs E)
{
如果(backgroundWorker1.CancellationPending)
{
e.Cancel = TRUE;
}
,否则
{
VAR QRY = e.Argument作为EnumerableRowCollection< CheckTrans.IndividualCheckRow取代;
如果(QRY!= NULL)
{
Thread.sleep代码(4000);

//item.Status = ach.SubmitCheck(项目);
变种ACH =新SubmitAchChecks();
的foreach(在QRY VAR项)
{
ach.SubmitCheck(项目);
backgroundWorker1.ReportProgress(1);
Console.Write(backgroundWorker1_dowork =+ progressBar1.Value.ToString()+\r\\\
);
}
}

}

}

我的取消按钮:

 私人无效cancelAsyncButton_Click(对象发件人,EventArgs五)
{
如果(backgroundWorker1.WorkerSupportsCancellation ==真)
{
label_Status.Text =取消...
backgroundWorker1.CancelAsync();
}
}



我backgroundWorker1_RunWorkerCompleted:

 私人无效backgroundWorker1_RunWorkerCompleted(对象发件人,RunWorkerCompletedEventArgs E)
{
如果(e.Cancelled ==真)
$ { b $ b label_Status.Text =取消了!
}
,否则如果(!e.Error = NULL)
{
label_Status.Text =错误:+ e.Error.Message;
}
,否则
{
label_Status.Text =完成!;
}
SubmittingAch(假);
}



我backgroundWorker1_ProgressChanged:

 私人无效backgroundWorker1_ProgressChanged(对象发件人,ProgressChangedEventArgs E)
{
progressBar1.Value + = 1;
Console.Write(progressbar1.value =+ progressBar1.Value.ToString()+\r\\\
);
}

当我处理2项我获得以下在我的调试窗口输出:



backgroundWorker1_dowork = 0


backgroundWorker1_dowork = 0



progressbar1> .value的= 1



progressbar1.value = 2



该事件被触发,但你可以看到从在console.write,它的发生后的线程完成。我得到的进度滚动,但只有一次的DoWork的完成。



我做了什么不对的呢?我想它来更新每个项目已完成。


解决方案

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


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().

这篇关于C#BackgroundWorker的进度与更新过程完成后,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆