Ensuring the creation of child controls in the main user interface thread

I am modifying an existing WinForms project. The project has a UserControl. This UserControl has a DataSet variable that is set from another part of the program to another thread.

What I want to do is dynamically add other controls to this element depending on the DataSet.

So, after loading the DataSet, I call the RefreshChildControl function and try to add my new ChildUserControls elements to flowLayoutPanel. And this is where the problems begin :). I get the Cross Stream operation invalid: The ChildUserControl control is accessible from a stream other than the one that was created in the exception. I tried to use if (this.InvokeRequired) and call this method, but that does not help. InvokeRequired on MyUserControl - false.

So, is there a good way to accomplish such a task? Or am I missing something important?

EDIT:

I tried to skip the InvokeRequired test and just call this.FindForm (). Call this method. My Invoke or BeginInvoke cannot be called in the control until the window handle is created. ”An exception. And by the way, when I open another form using this control, everything works fine.

0
multithreading c # winforms
source share
2 answers

At first. The easiest solution is to run Invoke every time. Nothing bad will happen. Second, use the SynchronizationContext.

using System.Threading; public class YourForm { SynchronizationContext sync; public YourForm() { sync = SynchronizationContext.Current; // Any time you need to update controls, call it like this: sync.Send(UpdateControls); } public void UpdateControls() { // Access your controls. } } 

SynchronizationContext will manage all thread issues for you. It checks if you are calling the same or different thread. If he immediately executes your code. Otherwise, it will execute Invoke through the form's message loop.

+2
source share

If your user control does not immediately appear after it is created, the handle will not be created in the stream that you think is created. This is not a C # object whose parent thread is important, this is a Windows Handle object whose parent is important.

To force the control to be instantly created in the thread that you think you created it, then read control.Handle , which will cause the control to actually be assigned and the handle is assigned.

  MyUserControl uc = new MyUserControl(); // the handle is not created here uc.Visible = false; IntPtr dummy = uc.Handle; // The control is immediately given a real handle 

You can also try playing with uc.CreateControl, but this will not create a handle if the control is not displayed.

You may now have a different thread updating your user control, even if the user control is not displayed.

  uc.BeginInvoke((Action)(() => uc.Text = "ha ha")); 

If you leave the line dummy = uc.Handle , you will get an exception that you cannot call BeginInvoke for a control that does not have a handle.

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.createcontrol(v=vs.90).aspx

+1
source share

All Articles