![](/img/trans.png)
[英]How do i use backgroundworker with timer and progressBar?
[英]How do I use backgroundworker in this instance?
我有一个关于后台工作者如何实际工作的问题。 我不太确定如何使用不同的方法。
例如,我有以下代码(改编自http://broadcast.oreilly.com/2010/06/understanding-c-using-backgrou.html用于说明目的):
private void getDateTime()
{
DateTime startTime = DateTime.Now;
double value = Math.E;
while (DateTime.Now < startTime.AddMilliseconds(100))
{
value /= Math.PI;
value *= Math.Sqrt(2);
}
}
private backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for(int i=0; i <= 100; i++)
{
getDateTime();
backgroundWorker1.ReportProgress(i);
}
}
这将使用backgroundworker线程不断计算DateTime。 现在我假设backgroundworker的DoWork方法中的for循环将运行计算,报告进度,然后重复循环(如果我误解,请纠正我)。
现在假设我有另一个方法,它解析一个(可能是大的)DataTable并返回另一个DataTable,在后台工作中使用它意味着我将一遍又一遍地解析DataTable(理论上再次,如果我错了,请纠正我) ? 如果这是程序的流程,是否有更有效的方法来实现DataTable解析而不必重复循环,但仍然能够使用backgroundworker?
这适用于Windows窗体,当我解析DataTable时,UI往往会冻结。 我听说背景工作者可以帮助我解决UI的问题,但我发现重新解析整个DataTable的效率非常低。 但是,我不确定我是否可以在没有for循环的情况下报告进度。
编辑:
我找到了一个临时解决方案。 它有效,但我仍无法报告进展情况。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int rows = (int)e.Argument;
int count = 0;
t3 = runComparison();
for (int i = 0; i <= rows; i++)
{
count++;
int current = count / rows;
backgroundWorker1.ReportProgress(current * 100);
}
e.Result = t3;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("An unexpected error has occurred. Please try again later.", "ERROR!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
dataGridView1.DataSource = e.Result;
}
}
我知道我的for循环没有做任何事情。 但是,“runComparison”已经耗费了大量时间。 因此,如果它处于for循环中,则直到整个运行期才会报告进度。 或者,也许我可以使用标签或消息框而不是进度条。 不太确定我应该怎么做到这一点。
尝试这样做:
//make sure background worker report progress
backgroundWorker1.WorkerReportsProgress = True;
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
progressBar1.Refresh;
//if your progressbar is on a status strip, you need to refresh the status strip instead
}
我想出了一个相当不优雅的解决方案。 但它满足了用户友好性的要求所以......无论如何工作:P
感谢所有的反馈,我很感激。
无论如何,这是代码:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
backgroundWorker1.ReportProgress(1); //to invoke ProgressChanged
t3 = runComparison(); //run intensive method
e.Result = t3; //return DataTable
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Visible = true; //display a label
textBoxProgress.Visible = true; //display the progress bar
//change the progress bar style
//the Marquee style is constantly running, so it could show users the process is working
//not too sure how to explain it, you'll have to try it out.
progressBar1.Style = ProgressBarStyle.Marquee;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("An unexpected error has occurred. Please try again later.", "ERROR!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
//reset the display and update the DataGridView
progressBar1.Visible = false;
textBoxProgress.Visible = false;
progressBar1.Style = ProgressBarStyle.Blocks;
dataGridView1.DataSource = e.Result;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.