0

我的程序上有一个进度条,我试图在处理完每个“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 条记录,所以我应该能够看到它,因为它处理所有记录大约需要一分钟。

4

3 回答 3

4

假设所有这些都发生在 UI 线程中,那么它不会更新,因为您让线程忙于处理您的循环。您需要生成一个后台线程来进行处理,这样它就不会挂起您的 UI 线程。然后,您需要将实际设置进度条的部分推回您的 UI 线程,使用Contol.Invoke.

请参阅此处: http: //msdn.microsoft.com/en-us/library/zyzhdc6b.aspx的线程示例(尽管有很多方法可以做到这一点)和Control.Invoke.

于 2013-08-13T13:21:50.030 回答
1

使用后台工作者:

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.
}
于 2013-08-13T14:00:08.670 回答
0

由于您的循环阻塞了活动线程,您将不得不使用另一个线程(干净的方式)或简单地在 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();
于 2013-08-13T13:22:10.540 回答