Click here to Skip to main content
15,881,027 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have the following in an app (WinForms, C#) using a BackgroundWorker and a DataGridView.

Works fine for small datasets, but blows up when there are a boatload of rows. Binding source error, DataMember and DataSource can't be the same, blah blah blah. Which they're not. It's a threading issue.

C#
private void bkTrashCollection_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
  {
    BadFiles = 0;
    CollectTrash();
  }

private void CollectTrash()
  {
    foreach (DataGridViewRow Row in tbl_MediaDataGridView.Rows)
    {
      string FilePath = Row.Cells[3].Value.ToString();

      if (!File.Exists(FilePath))
      {
        MissingFiles.Add(FilePath);
        Row.DefaultCellStyle.BackColor = Color.Yellow;
        BadFiles += 1;
      }
  }
}


Where do I put the Lock or Invoke or whatever so it will work? None of the examples I've found work, except to make the changing of the BackColor not happen at all, rather than at least working half the time. :sigh:

I think a workaround would be to use that "MissingFiles" list to do the color changes when it comes out of the background thread, but I'd rather do it all in one swell foop, if possible.

Is it possible?
Posted

1 solution

You're accessing the control from a worker thread, which is illegal. If you run this in the debugger, an exception will be thrown to warn you.

Putting the call to File.Exists in a separate thread is a good idea, but you must get the file paths and set the backgrounds on the UI thread.

You also have the problem that the data in the grid might change while your thread runs.

A solution would be to create a collection of file paths on the UI thread and pass that to your BackgroundWorker. Then in your completed handler ( which runs on the UI thread ) search the grid again and set the background for missing files.

You'll have to test this for performance on "a boatload of rows" :)

Nick
 
Share this answer
 
Comments
GenJerDan 15-Oct-10 12:01pm    
Wondering: would I also be better off checking the existence of the files directly from the underlying table, instead of via the DataGridView? The table won't change very often, and if the user *does* want to change it, I can kill the thread and run the process "next time".

Then use that list, as you said, to change the grid in the UI thread.

The thing was threaded just so the user doesn't have to sit there waiting and waiting and waiting while housekeeping is being performed, but it's not overly vital that it takes place uninterrupted every time the user starts the app.
GenJerDan 15-Oct-10 12:04pm    
Oh, yeah, another thing which others might find helpful in other situations: I *do* run this in the debugger, and it never complained about it until recently...when I went from 10 rows in the underlying table to about 17,000. So it really really pays to test things with the expected data, not just a handful of test data.
Nicholas Butler 15-Oct-10 12:17pm    
Are you running the Debug build? It should throw as soon as you touch the grid from the background thread.

Yes, you can get the file paths from the underlying data, as long as you match it up to the current data in the grid when you set the backgrounds.

Also, I think it is imperative you call File.Exists on a background thread. It could take 30 seconds per file if there are network problems and you don't want the UI thread to block.

Nick
Nicholas Butler 15-Oct-10 12:23pm    
Just saw... 17,000 files !!! Do you really want to show that many in one go?
GenJerDan 15-Oct-10 15:04pm    
17,000 at the moment...if I did a full gathering, it might be twice that. Never got the hang of paging and such, though, especially when he user can sort the data anywhichway.
I ran up a version using what we've spoken of and it works without a hiccup, so I guess This problem is solved. Thanks!
I may change it to use the record number (an actual id field), rather than the filename when it comes to the find-and-change-color part. I don't know if it makes a difference, but finding an integer match might be faster than finding a string match. I'll test it both way and see if it matters.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900