Hello,
I'm converting an existing application from .NET1.1 to NET 2.0. The app. has a form and a custom container control with many children controls on it. The form, container control, and all children are created in the main thread. At some point a user clicks a button on the container control and the following happens:
1. A new container control gets created and added to the form (in the main thread)
2. A new thread starts to load data for the newly created container control.
3. The old container control is disposed by a direct call to Dispose() from the main thread.
4. One of the old container's children control's Dispose method fails:
System.InvalidOperationException: Cross-thread operation not valid: Control 'CCity' accessed from a thread other than the thread it was created on.
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.DestroyHandle()
at System.Windows.Forms.Control.Dispose(Boolean disposing)
....
In the debugger, I verified that this control was created in the main thread (tracking the thread id in the Treads window). I set breakpoints inside the Dispose methods of the control and it's parent. In both cases the Threads window shows the same thread (the main thread) that control was created in. However, for the parent container control InvokeRequired is false inside it's Dispose(), but for the child it is set to true.
If I call Dispose() on the old container before starting a new data-loading thread (move the item #3 to the top), then everything works fine. It looks like inside the Control.Dispose() method the framework fails to correctly detect in which thread the control was originally created.
Has somebody else encountered a similar problem I appreciate any input on this issue.
Thank you,
Leonid

"Cross-thread operation not valid" exception inside the Control.Dispose()
Angry Coder
this is actually by design - you cannot call a UI control from a thread which the control was not created from. The way to get around this problem is to invoke the control using a delegate for example - this is thread safe otherwise you would expect some unexpected results of cross threading.
since I am unfortunately not at home right now, I would have normally provided an example from my projects but for now I hope this helps:
http://blogs.msdn.com/scottno/archive/2004/07/26/197773.aspx
http://msdn2.microsoft.com/en-us/library/zyzhdc6b.aspx
hope these help for now
Sarwanan
ok, here is an example:
//main form:
public delegate void DoUpdateLabel(string theText);
..
..
public void DoUpdateUILabel(string theText)
{
if (this.theLabel.InvokeRequired)
{
DoUpdateLabel theUpdateLabelDelegate = new DoUpdateLabel(DoUpdateUILabel);
this.Invoke(theUpdateLabelDelegate, new object[] { theText });
}
else
{
this.theLabel.Text = theText;
}
}
//some other method in a thread
this.DoUpdateUILabel("hello, this was called from a thread");
thats all there is to it
does this help
simon_
Thank you for your post.
May be I didn't say it clear, but the problem is that I create a control, add it to the parent, and then dispose the parent in the same main thread. However, just before disposing a parent, I'm starting a new thread. When I call parent.Dispose() in the main thread, it internally calls Dispose() on my contrlol. The latter fails with the "cross-thread" exception, and I don't see any reason for this, because everything happens in the main thread.
Am I correct assuming that the logic behind the "cross-thread" exception relies on InvokeRequired How does exactly InvokeRequired work I've seen posts describing it not working properly before the handle for the control has been created, but it is different in my case - I definetely got the control created in the main thread.
Leonid.
Gonzales234
UnknownScripter
Possibly, the problem started when you originally created the child control. If that was done by a thread other than the one that created the parent, you would indeed see this behavior...
If you're pretty sure this isn't really creating a problem, you can temporarily surpress the exception by using Control.CheckForIllegalCrossThreadCalls = false
Ganesh sethuraman
Paul Monaghan
Can anyone solve our problem
Thanks in advance.
Christian Sparre
I have the same problem (with VB2005) :
I have a control (a designer control ) with other controls designed on it.
I always call dispose from the main thread. The main thread previously instanciated the contol.
It works fine about 3999 times/4000. But sometimes it crashes : it get a cross thread exception.
I tried to look at invokerequired property and do a control.invoke when this property is set to true but it deadlocked !
When i looked why It deadlocked, i saw that my control invoked in the same thread (the main thread)
It seems that sometimes, InvokeRequired returns not the accurate value and the detection of cross thread has a problem.
I can't use Control.CheckForIllegalCrossThreadCalls because it is a shared member and I'm not allowed to suppress the detection of cross-thread in the whole application.
Does anybody have an idea or a workaround
Thanks