Is there a way to find the control flow?

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 :)

+6
multithreading c #
source share
1 answer

To get the owner stream for the control, try the following:

 private Thread GetControlOwnerThread(Control ctrl) { if (ctrl.InvokeRequired) ctrl.BeginInvoke( new Action<Control>(GetControlOwnerThread), new object[] {ctrl}); else return System.Threading.Thread.CurrentThread; } 

Can child controls be in a different thread from the parent (container control)? Yes, it all depends on which thread worked when constructing the control (new'ed up)

You always need to check InvokeRequired ... since you never know which thread can call the method you are encoding ... If you need to check InvokeRequired separately for each child control, it depends on how confident you are that everything controls were created in the same stream or not. If all the controls are created when the form is created, in the same initialization procedure, then you can probably safely assume that they are all created in the same thread

+3
source share

All Articles