Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > Cross-thread operation not valid when DataBinding on DataSource for datagrid.
 

Cross-thread operation not valid when DataBinding on DataSource for datagrid.

Hello, we have run in to an issue we keep getting the anoying "Cross-thread operation not valid" error message. Normaly i would have thought i knew how to fix this with InvokeRequired and Invoke, but apparently not.

Here is the piece of code that causes the problem (or at least apears to do so, don't mind the trace messages, that was just part of trying to figure out just what is going on since it keept comming with the error. The line that throws the exception is #12.
01        private void PopulateListView()
02        {
03            if (InvokeRequired)
04            {
05                Trace.WriteLine("Invoke Required: " + Thread.CurrentThread.ManagedThreadId);
06                Invoke(new Action(PopulateListView));
07            }
08            else
09            {
10                Trace.WriteLine("Invoke Not Required: " + Thread.CurrentThread.ManagedThreadId);
11                presentationModel.Refresh();
12                runtimeLogMessageBindingSource.DataSource = presentationModel.LogEntries;
13                SetMessage();
14            }
15        }

now i would have though that the above should take care of cross thread operations by using "Invoke", but even then the error occurs.

The stack trace and message as folow:
Cross-thread operation not valid: Control 'dgvLogMessages' accessed from a thread other than the thread it was created on.

   at System.Windows.Forms.Control.get_Handle()
   at System.Windows.Forms.Control.SendMessage(Int32 msg, Int32 wparam, Int32 lparam)
   at System.Windows.Forms.Control.BeginUpdateInternal()
   at System.Windows.Forms.DataGridView.RefreshColumns()
   at System.Windows.Forms.DataGridView.RefreshColumnsAndRows()
   at System.Windows.Forms.DataGridView.DataGridViewDataConnection.DataSourceMetaDataChanged()
   at System.Windows.Forms.DataGridView.DataGridViewDataConnection.ProcessListChanged(ListChangedEventArgs e)
   at System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e)
   at System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e)
   at System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e)
   at System.Windows.Forms.BindingSource.OnListChanged(ListChangedEventArgs e)
   at System.Windows.Forms.BindingSource.ResetBindings(Boolean metadataChanged)
   at System.Windows.Forms.BindingSource.SetList(IList list, Boolean metaDataChanged, Boolean applySortAndFilter)
   at System.Windows.Forms.BindingSource.ResetList()
   at System.Windows.Forms.BindingSource.set_DataSource(Object value)
   at Systematic.OMSIS.Runtime.Presentation.ManagementGUI.Controls.ManagementLog.PopulateListView() in C:\CEN\JSF-OMS-IO\Branch_Release-Increment_C\src\Runtime\Presentation\ManagementGUI\Controls\ManagementLog.cs:line 56
   at Systematic.OMSIS.Runtime.Presentation.ManagementGUI.Controls.ManagementLog.RefreshComponent() in C:\CEN\JSF-OMS-IO\Branch_Release-Increment_C\src\Runtime\Presentation\ManagementGUI\Controls\ManagementLog.cs:line 99
   at Systematic.OMSIS.Runtime.Presentation.ManagementGUI.ManagementUIPresentation.Refresh() in C:\CEN\JSF-OMS-IO\Branch_Release-Increment_C\src\Runtime\Presentation\ManagementGUI\ManagementUIPresentation.cs:line 138
   at Systematic.OMSIS.Runtime.Presentation.ManagementGUI.ManagementUIPresentation.StatusChangedEventHandler(Object sender, ServiceStatusUpdateEventArgs args) in C:\CEN\JSF-OMS-IO\Branch_Release-Increment_C\src\Runtime\Presentation\ManagementGUI\ManagementUIPresentation.cs:line 160
   at Systematic.OMSIS.Runtime.Presentation.Services.RuntimeServiceMonitor.PollRuntimeServiceStatus() in C:\CEN\JSF-OMS-IO\Branch_Release-Increment_C\src\Runtime\Presentation\Services\RuntimeServiceMonitor.cs:line 183
   at Systematic.OMSIS.Runtime.Presentation.Services.RuntimeServiceMonitor.<Start>b__0(Object timerCallback) in C:\CEN\JSF-OMS-IO\Branch_Release-Increment_C\src\Runtime\Presentation\Services\RuntimeServiceMonitor.cs:line 130
   at System.Threading._TimerCallback.TimerCallback_Context(Object state)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading._TimerCallback.PerformTimerCallback(Object state)
Am i overlooking something?.

Jmelgaard  Tuesday, September 01, 2009 9:38 AM
We have tried to direct the calls to the controll directly as well.Did not help at all.
The other part we haven't since that would cause an endless loop unless we made it into 2 methods.

We haven't gotten around to that since we ended up being a bit drastic. As such we cleaned up alot of code.
What seems to have removed it that our calls now "travel" throug less layers.

As before it was pritty much

1. Example: Call from service
WCF ---- event ----> PM ---- event ---->   Form
                                            ||
                                            ||
                                     refresh components
                                            ||
                                            \/
DA <---- call ----   PM <---- call ----- Component



2. Examble: Call from service watcher
SW  ---- event ----> PM ---- event ---->   Form
                                            ||
                                            ||
                                     refresh components
                                            ||
                                            \/
DA <---- call ----   PM <---- call ----- Component

Both the WCF Callback and the ServiceWatcher would make there call on different threads, within the form and components the previous code applies for both components and form.

What seems to have removed the issue is a change in that call stack. so it is more like:

1. Example: Call from service
WCF/SW ---- event ----> PM
                        ||
                        ||
                     refresh
                        ||
                        \/
DA    <---- call ----   PM
                        ||
                        \/
                        PM ---- event ---->   Form
                                               ||
                                               ||
                                       refresh components
                                               ||
                                               \/
                        PM <---- call ----- Component

As a side effect things also become more clear cut and gennerally better code.
So thats all good, but i have no idea why it failed before with the more direct aproach.

I Will mark this as an awnser to close the thread since we don't have the issue anymore even though it can't really help others if they come in the same situation i belive. :S
  • Marked As Answer byJmelgaard Wednesday, September 02, 2009 8:39 AM
  •  
Jmelgaard  Wednesday, September 02, 2009 8:38 AM
I haven't looked at this in depth, but on the surface it seems strange.

Try directing the InvokeRequired directly to the control in question (e.g.,dgvLogMessages.InvokeRequired) instead Form (I presume). Similarly adjust the Invoke to dgvLogMessages.Invoke. If this solves it, consider whether you might have created the Form using a separate thread than the one thatcreated the dgvLogMessages control.

Another thing to try if the above does help, what happens if you always run the Invoke() code, even if InvokeRequired returns false.
BinaryCoder  Wednesday, September 02, 2009 12:41 AM
We have tried to direct the calls to the controll directly as well.Did not help at all.
The other part we haven't since that would cause an endless loop unless we made it into 2 methods.

We haven't gotten around to that since we ended up being a bit drastic. As such we cleaned up alot of code.
What seems to have removed it that our calls now "travel" throug less layers.

As before it was pritty much

1. Example: Call from service
WCF ---- event ----> PM ---- event ---->   Form
                                            ||
                                            ||
                                     refresh components
                                            ||
                                            \/
DA <---- call ----   PM <---- call ----- Component



2. Examble: Call from service watcher
SW  ---- event ----> PM ---- event ---->   Form
                                            ||
                                            ||
                                     refresh components
                                            ||
                                            \/
DA <---- call ----   PM <---- call ----- Component

Both the WCF Callback and the ServiceWatcher would make there call on different threads, within the form and components the previous code applies for both components and form.

What seems to have removed the issue is a change in that call stack. so it is more like:

1. Example: Call from service
WCF/SW ---- event ----> PM
                        ||
                        ||
                     refresh
                        ||
                        \/
DA    <---- call ----   PM
                        ||
                        \/
                        PM ---- event ---->   Form
                                               ||
                                               ||
                                       refresh components
                                               ||
                                               \/
                        PM <---- call ----- Component

As a side effect things also become more clear cut and gennerally better code.
So thats all good, but i have no idea why it failed before with the more direct aproach.

I Will mark this as an awnser to close the thread since we don't have the issue anymore even though it can't really help others if they come in the same situation i belive. :S
  • Marked As Answer byJmelgaard Wednesday, September 02, 2009 8:39 AM
  •  
Jmelgaard  Wednesday, September 02, 2009 8:38 AM

You can use google to search for other answers

Custom Search

More Threads

• How do i create a checkbox column in an Datagridview
• How to run multiple reports on a reportviwer
• how to create a new DataGridViewCellValidatingEventArgs object
• Get RowIndex of selected cell in DataGridView on buttonClickEvent
• Keyboard shortcuts within a datagridview
• BindingComplete event isn't firing - why?
• Please Help - custom objects/collections and datagrids
• Relationship and currency manager
• DataGridView add new row WITHOUT typing
• How to make read only to particular row of datagridview on load event of form?