I want to loop through a DataGridView that is created on the main form in a BackgroundWorker to export the data to a CSV file. The BackgroundWorker is created on a separate form where the progress of the export will be displayed via a progress bar. Here is the code on the export form that calls the BackgroundWorker:
private DataGridView exportGrid;
public void ExportCSV(DataGridView mainGrid)
{
this.exportGrid = mainGrid;
//Set progress bar maximum
progressBar1.Maximum = mainGrid.Rows.Count;
if (backgroundWorker1.IsBusy != true)
{
//Start the asynchronous operation
backgroundWorker1.RunWorkerAsync();
}
//Show the form
this.ShowDialog();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
//Write data rows
foreach (DataGridViewRow row in exportGrid.Rows)
{
//Check if the background worker has been cancelled
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
foreach (DataGridViewCell cell in row.Cells)
{
if (cell.Visible)
{
//Do CSV writing here...
}
}
//Report current progress to update UI
worker.ReportProgress(row.Index + 1);
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Update progress bar
this.progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Close the form once the background worker is complete
this.Close();
}
This code has been causing the following errors:
- BindingSource cannot be its own data source. Do not set the
DataSource and DataMember properties to values that refer back to
BindingSource. - Cross-thread operation not valid: Control ‘mainGrid’ accessed from a
thread other than the thread it was created on.
I assume that these are because I am accessing the DataGridView in a thread that did not create it. What is the best way to go about doing this? Is it even possible?
Update:
The reason I am looping through the DataGridView instead of the datasource is that the users will be changing the column order, sort order and showing/hiding columns of the grid and they want these changes reflected in the exported data. Is there a different way to handle this?
Jeff in my opinion you are doing at minimum two mistakes in here:
I just would not try to access a UI control (Grid in your case) in a form which is not even the form where the background thread is declared, code will be so unclear and unreadable…
then consider that UI controls are used to render data in the UI; whenever you need to access the data for anything else than rendering in the screen you’d better access directly the datasource used to populate the UI.