views:

68

answers:

1

Hi,

I have two machines, one is an old toshiba laptop that I use at home for development, the other is a 1 year old dell at work. Both are running the same version of visual studio 2008. I have been, for the last several months, building a project for a client. It runs fine on my old laptop, but if I run it in the same environment at work I get cross threading issues, anybody have an idea why? Is there something in the project/environment that I need to check or uncheck...

The problem has occurred ever since I added a tab control to the main user interface. The cross threading error occurs when loading the main form, when the tab control is dynamically resized - I have made it react like an expandable panel so the user can hide it if it is not being used.

This is the line is fails on, this is in the main load section:

expandable_tabcontrol.Left += expandable_tabcontrol.Width;

This is the error message:

An unhandled exception of type 'System.InvalidOperationException' 
occurred in System.Windows.Forms.dll

Additional information: Cross-thread operation 
not valid: Control 'frmUserInterFace' accessed 
from a thread other than the thread it was created on.

Runs fine at home, fails at work...

Thanks, R.

+2  A: 

It's difficult to be certain without a little more information, but it sounds to me like the method that does the resizing can be called in more than one place. It's likely that your old Toshiba is a single-core machine, so the computer can't do more than one thing at once and the tab is resized by the main thread. On your newer Dell machine, which likely has multiple cores, a secondary thread is calling the method that does the resizing, and that's causing the exception to be thrown.

Look into the use of Control.InvokeRequired and Control.Invoke to handle synchronization between background threads and the UI thread.

Jim Mischel
I agree with the first paragraph. However, don't use `Invoke`, and certainly don't use `InvokeRequired`. Use a `Task` or a `BackgroundWorker`.
Stephen Cleary
If you want to update the UI from a thread other than the worker thread, you'll definitely need to use Invoke or something similar. A system timer event handler, for example, will have to use that. Does BackgroundWorker have an Invoke equivalent for updating the UI?
Jim Mischel
Ok, this made total sense and I added a delegate to the timer method that is used to expand and contract the panel. When it is loading, I also locked the form creation method and initial panel adjustment and all the errors are now gone. These comments were very useful, thanks.
flavour404
Ok, totally premature, nope still causing the same error. Took all the resize on load code out and set the control to its starting size, and put the label where I want it, but still erroring out when trying to display the form.
flavour404
@flavour404: The error message means that the you have more than one thread running, and a non-UI thread is trying to update the form. You need to identify the thread (a timer, perhaps?) that's trying to access the UI. If you want to update the UI from a non-UI thread, you'll need to use Control.Invoke or something similar.
Jim Mischel
I managed to work around the problem and stop the error. It was in fact a despatch timer, instantiated on form load that was causing the threading error. I since moved the despatch timer instantiation code to a button, so the first time the button is pressed the timer is created, and this has stopped the threading errors. Everything is working fine now, looks at the logs, no errors. All the answers were very helpful. Thanks.
flavour404