我的程序上有一个进度条,我试图在每个“DataTable”处理完毕后为它添加值,但只有在完成所有操作后才会更新。
这是代码:
int c = 0;
OdbcConnection cn = openOdbcDB();
foreach(DataSet ds in allDataSets)
{
foreach(DataTable dt in ds.Tables)
{
foreach (DataRow dr in dt.Rows)
{
insertIntoDatabaseCurrentRecord(dr);
}
}
pbMain.Value = pbMain.Value + (33 / totalFiles);
c++;
}
cn.Close();
cn.Dispose();
有没有办法强制栏在每个表完成后显示进度,就像它完成一样?此刻,我只看到循环完成后的进度,我看到线条从空到满。每个DataTable大约有18000条记录,所以我应该可以看到它,因为它需要大约一分钟来处理所有记录。
答案 0 :(得分:4)
假设所有这一切都发生在UI线程中,那么它就不会更新,因为你让线程忙于处理你的循环。您需要生成后台线程来进行处理,以便它不会挂起您的UI线程。然后,您需要使用Contol.Invoke
将实际设置进度条的部分推回到UI线程。
请参阅此处:http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx以获取线程示例(尽管有很多方法可以执行此操作)和Control.Invoke
。
答案 1 :(得分:1)
使用BackgroundWorker:
BackgroundWorker _worker;
// executes on another thread
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
int c = 0;
OdbcConnection cn = openOdbcDB();
foreach (DataSet ds in allDataSets)
{
foreach (DataTable dt in ds.Tables)
{
foreach (DataRow dr in dt.Rows)
{
insertIntoDatabaseCurrentRecord(dr);
}
}
// do not update UI elements here, but in ProgressChanged event
//pbMain.Value = pbMain.Value + (33 / totalFiles);
c++;
worker.ReportProgress(c); // call ProgressChanged event of the worker and pass a value you can calculate the percentage from (I choose c, since it is the only calculated value here)
}
cn.Close();
cn.Dispose();
}
// gets called on your main thread
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// update the progressbar here.
// e.ProgressPercentage holds the value passed in DoWork.
}
答案 2 :(得分:0)
由于你的循环阻塞了活动线程,你必须使用另一个Thread(干净的方式)或者只是在WinForms上使用Application.DoEvents():
int c = 0;
OdbcConnection cn = openOdbcDB();
foreach(DataSet ds in allDataSets)
{
foreach(DataTable dt in ds.Tables)
{
foreach (DataRow dr in dt.Rows)
{
insertIntoDatabaseCurrentRecord(dr);
Application.DoEvents(); //Quick and dirty
}
}
pbMain.Value = pbMain.Value + (33 / totalFiles);
c++;
}
cn.Close();
cn.Dispose();