0

I have a progress bar on my program and I am trying to add value to it after each "DataTable" has been processed, however it only updates after everything is done.

here is the code:

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

Is there a way to force the bar to show progress after each table is finished like it is finished? At the moment, I only see the progress once loops finish, I see the line go from empty to full. There are about 18000 records per DataTable, so I should be able to see it because it takes about a minute for it to process all the records.

Bagzli
  • 6,254
  • 17
  • 80
  • 163

3 Answers3

4

Assuming all this is happening in the UI thread, then it's not going to update because you are keeping the thread busy with processing your loop. You need to spawn off a background thread to do the processing so that it doesn't hang your UI thread. Then you will need to have the part where you actually set the progress bar pushed back to your UI thread using Contol.Invoke.

See here: http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx for both an example of threading (although there are many ways you can do this) and Control.Invoke.

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
1

Use 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.
}
Kai Hartmann
  • 3,106
  • 1
  • 31
  • 45
0

Since your loops are blocking the active thread, you will have to use another Thread (clean way) or simply use Application.DoEvents() on WinForms:

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();
MS_SP
  • 218
  • 2
  • 9