I have some problems with a thread with a large application I'm working on (getting exceptions for cross threads). Is there a way to find the name / id of the thread on which the specific control was created?
An error occurs when I try to add a new control to my control collection. I cannot create a small reproducible sample, so I will describe it as best as possible.
I have a main control that is on a form, call it _mainControl. In its constructor, I instantiate another control, something like
ChildControl _childControl = new ChildControl();
_ChildControl now exists, but I havenโt added it to the _mainControls collection yet.
In the end, _mainControl receives an event notification that I must add to the control. In the event handler, I check if this.InvokeRequired is, and if so, I call the handler, something like the following:
AddControlEventHander(...) { if(InvokeRequired) { BeginInvoke(new MethodInvoker(AddControlEventHander); return; } Controls.Add(_childControl); }
An exception is always thrown in Controls.Add ("Invalid cross-thread operation: Control '_item' accesses from a thread other than the thread that was created on").
Now I do not understand how this is possible. I created _childControl in the same thread on which _mainControl was created. When I look at the threads window during debugging, the current thread name / id is the same as when I call Control.Add in the same way as when adding _childControl. However, the following calls from _mainControl bother me the most:
InvokeReuqired == false; _childControl.InvokeRequired == false; _childControl._item.InvokeRequired == true; //I made _item public just to try this and it returns true!
How is this possible? Is it possible to create _childControl on a single thread while its children are somehow created? All _childControl children are created during initialization, as is usually done.
If anyone has any tips / suggestions on what might happen, let me know.
Thanks.
Edit:
In case someone is interested, I found out what is happening. I was curious how to create a control on one thread, and then children are created on another thread, although InitializeComponent was made in one thread. So, I found out which thread was created for the child using a code similar to what Charles suggested below. As soon as I realized this, at least I knew which thread to focus on. Then I broke the OnHandleCreated event of the child control and found the problem.
One thing that I did not know about is that the handle to the control is created when the control first becomes visible, and not when it is created. Thus, a thread that does not own a control tried to set its visibility to true. So I added a check to see if InvokeRequired and thought it would do the trick. However, I really did not expect the InvokeRequired call to create a handle to the control, if not already created! This actually causes the control to be created in the wrong thread and always returns false for InvokeRequired. I got around this by touching the Handle property of the control so that it was created before InvokeRequired was called.
Thanks for helping the guys :)