进程完成后,C#BackGroundWorker与ProgressBar更新
我在按钮点击事件中有以下内容:
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; 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。
我做错了什么? 我希望在每个项目完成后更新。
这是由于线程的工作方式。 使用BeginInvoke
在UI线程上调用ProgressChange
,因此在另一个线程上调用。 同时,工作线程继续运行。 由于没有太多工作要做, BackgroundWorker
在BeginInvoke
实际调用该方法之前完成其工作,因为每次CPU操作都不会发生线程切换。 它们发生在不少之后。 为避免这种情况,请使用this.Invoke()
手动调用增加ProgressBar
值的方法。