2

For a project I am working on I have a form with a bunch of DataGridView components that are to display some data. Every DataGridView has it's own DataTable associated it. The data that is to be displayed is send periodically. My application has to read this data, parse it and fill the datagrids accordingly. Because I want to maintain responsiveness of the form I implemented the receiving of data (blocking) in an endless background worker.

In the background worker I obtain the data and parse/convert it into values that fit in the DataTables. Now here is my question: At the moment I assign these values directly to the DataTable objects. (So I do this from within the backgroundworker's DoWork event)

I am wondering if this is valid. I did have an index out of bounds exception once and I was wondering if this was somehow associated with this. Is this a safe and recommended way of doing it, or should I use invokes in my backgroundworker's DoWork event to update the DataTables?

casperOne
  • 73,706
  • 19
  • 184
  • 253
William W
  • 31
  • 3
  • Why would you use a single thread for this? It seems like you should use a Background Worker for each control. You should be doing Invokes, not exactly sure you are doing it, provide code if you want a more detailed response. – Security Hound Jul 11 '12 at 14:40

3 Answers3

3

No, all properties on .NET WinForm controls (this is the assumption) that affect the rendering of the control (including values bound to the control which would affect the rendering) must be made on the thread that created the control.

That said, there are many times when you will get away with being able to make the changes, but the behavior is unpredictable and not recommended.

In your specific case, I'd suggest having a copy of the DataTable that the processing thread works with, and then marshal that copy to the UI thread (through a call to one of the ISynchronizeInvoke interface implementation, which the Control class implements) and update the grid in the UI thread.

Basically, you'd perform an update of the DataTable that the grid is bound to with the copy marshaled from the background thread.

casperOne
  • 73,706
  • 19
  • 184
  • 253
  • I'm no familiar with WinForms... but in WPF, there is a dispatcher which can run code in UI thread. Wouldn't this be possible with winforms ? put all the datatable update in delegates called by this dispatcher ? – Kek Jul 11 '12 at 14:42
  • @kek Yes, you can do that, but what you're ultimately doing making a call to a background thread which then calls the UI thread and *then* does the work. The point is, you have to marshal the data from the background thread to the UI thread (whether it be through a call to `Invoke` in Windows Forms or the `Dispatcher` in WPF) after the background thread does all the heavy lifting. – casperOne Jul 11 '12 at 14:44
  • OK... the term marshalling was not clear to me... but yes, you'll have to work on a copy of the data first and copy it to. Thanks for clarification... +1 for the completeness of the answer – Kek Jul 11 '12 at 14:49
  • @Kek No problem, and yes, "marshal" is the general term for moving the call and/or data across boundaries, whether they be threads (background and UI), managed/unmanaged code (COM interop, P/Invoke). – casperOne Jul 11 '12 at 14:52
0

Well, no. Though it is a very good idea to do calculation in a background thread, UI update should be done in UI thread, always.

When binding Datatable to UI element, you "give" ownership on these objects to the UI thread and should no longer update them in background threads

Kek
  • 3,145
  • 2
  • 20
  • 26
  • I'm not updating the UI directly from the thread though, but only the structure bound to a UI component. So if I understand correctly this does not matter and it should still be done in the UI thread? – William W Jul 11 '12 at 14:41
  • @WilliamW Updating the structure will cause a chain reaction that will cause the re-rendering of the control in the UI thread. This should not be done. You have to have a copy of the structure, perform the work, and then marshal the data to the main thread and update the structure bound to the UI component there. – casperOne Jul 11 '12 at 14:47
0

It's fair to say that you should never update any UI bound elements from a non-ui thread. Although very often you may not see any exception if you do so, it never good practice, and often leads to exceptions or worse still, unseen errors

stevethethread
  • 2,524
  • 2
  • 30
  • 29