Re: Problem creating controls from other thread w/ invoke by Michael
Michael
Fri Dec 09 03:31:45 CST 2005
Stoitcho,
oh sorry, I forgot this one. This of course could have been the reason why
...thanks!
Regards,
Michael
"Stoitcho Goutsev (100) [C# MVP]" <100@100.com> schrieb im Newsbeitrag
news:em6RQBB$FHA.3308@TK2MSFTNGP11.phx.gbl...
> Michael,
>
> Sorry, I saw wrong. I though (saw) that you call Invoke on the invoker
> object.
> The problem is here:
> After you check that the call requires Invoke you correctly invoke the
> method in the UI thread. And the UI thread calls the methods recursively.
> This time InvokeRequired is false and you continue with control creation
> that by all rules succeeds.
>
> The methods executed by the UI thread finishes and the worker thread
> continues after the call *this.Invoke()*. At this point you should do
> *return* to cancel execution for the rest of the code. You fail to do that
> (no *return* statement) so the execution continues and goes through the
code
> of creating the control again this time in the worker thread. And here is
> the moment where you get the exception.
>
> You should change the code to look like
>
> if (this.InvokeRequired)
> {
> System.Diagnostics.Trace.WriteLine("Invoke was required");
> MethodInvoker invoker = new
> MethodInvoker(this.CreateCommunicatorControls);
> this.Invoke(invoker);
> }
>
> private void CreateCommunicatorControls()
> {
> System.Diagnostics.Trace.WriteLine("CreateCommunicatorControls
called");
>
> // check for invokation
> if (this.InvokeRequired)
> {
> System.Diagnostics.Trace.WriteLine("Invoke was required");
> MethodInvoker invoker = new
> MethodInvoker(this.CreateCommunicatorControls);
> this.Invoke(invoker);
> return; //NOTE: PAY ATTENTION ON THIS *RETURN*
> }
>
> // YOU DON'T NEED THE ELSE CLAUSE SINCE THE EXECUTION WON'T COME HERE
IF
> INVOKE IS REQUIRED
>
> System.Diagnostics.Trace.WriteLine("Invoke was not required");
>
> try
> {
> [...]
> // create controls and add them to a panel on the form
> this.panelCommunicator.Controls.Add(newCommCtrl);
> [...]
> }
> catch (Exception e)
> {
> System.Diagnostics.Trace.WriteLine(e.Message);
> }
> }
>
>
> --
> HTH
> Stoitcho Goutsev (100) [C# MVP]
>
> "Michael Groeger" <google.news@web.de> wrote in message
> news:uFE2YpA$FHA.3340@TK2MSFTNGP12.phx.gbl...
> > Hi Stoitcho,
> >
> > I know that I cannot parent control created in different threads. That's
> > why
> > I am already invoking the main UI thread (see the EventHandler
> > EventProxy_Initialized). It's very strange what's going on there which I
> > saw
> > after modifying the code a little:
> >
> > --------- snip ---------
> >
> > private void EventProxy_Initialized(object sender, EventArgs e)
> > {
> > CreateCommunicatorControls();
> > }
> >
> > private void CreateCommunicatorControls()
> > {
> > System.Diagnostics.Trace.WriteLine("CreateCommunicatorControls
> > called");
> >
> > // check for invokation
> > if (this.InvokeRequired)
> > {
> > System.Diagnostics.Trace.WriteLine("Invoke was required");
> > MethodInvoker invoker = new
> > MethodInvoker(this.CreateCommunicatorControls);
> > this.Invoke(invoker);
> > }
> > else
> > System.Diagnostics.Trace.WriteLine("Invoke was not
> > required");
> > try
> > {
> > [...]
> > // create controls and add them to a panel on the form
> > this.panelCommunicator.Controls.Add(newCommCtrl);
> > [...]
> > }
> > catch (Exception e)
> > {
> > System.Diagnostics.Trace.WriteLine(e.Message);
> > }
> > }
> >
> > --------- snip ---------
> >
> > After executing the code the output was the following:
> > CreateCommunicatorControls called
> > Invoke was required
> > CreateCommunicatorControls called
> > Invoke was not required
> > Controls created on one thread cannot be parented to controls on a
> > different
> > thread
> >
> > I was somehow wondered and diagnosted that the panelCommunicator was
> > running
> > on a different UI thread, because this.panelCommunicator.InvokeRequired
> > returned true. I still do not understand why because the panel gets
> > created
> > in the forms constructor's InitializeComponent() method.
> >
> > To answer your question Stoitcho:
> > I am getting a remote event via remoting. Since this event is not raised
> > from the UI thread I am required to create the controls from a different
> > and
> > invoke the main UI thread from that one. Each event registers a control,
> > prior to the event I do not know how many controls I need, that's why
the
> > controls get created dynamically.
> >
> > Regards,
> > Michael
> >
> >
> >
> > "Stoitcho Goutsev (100) [C# MVP]" <100@100.com> schrieb im Newsbeitrag
> > news:eAiycXA$FHA.3136@TK2MSFTNGP15.phx.gbl...
> >> Michael,
> >>
> >> You cannot parent control created in different threads. This Windows OS
> >> restriction. Further mode you cannot call methods and set properties of
a
> >> control from a different thread than the one created the control.
> >>
> >> In remoting scenarious this could be kind of tricky because all
> >> notifications that comes form the remote objects are executed in worker
> >> threads from the thread pool. Use Control.Invoke to marshal them to the
> >> UI
> >> thread.
> >>
> >> Why do you need to start this new thread in order to create the
controls?
> >>
> >> I hope you know that the following code executes
> >> this.CreateCommunicatorControls in a thread from the thread pool
> >>
> >> > MethodInvoker invoker = new
> >> > MethodInvoker(this.CreateCommunicatorControls);
> >> > this.Invoke(invoker);
> >>
> >>
> >> --
> >> HTH
> >> Stoitcho Goutsev (100) [C# MVP]
> >>
> >> "Michael Groeger" <google.news@web.de> wrote in message
> >> news:eC24jA%23%23FHA.1312@TK2MSFTNGP09.phx.gbl...
> >> > Hi,
> >> >
> >> > I have a form which acts as monitor for a service. The form and the
> >> > monitor
> >> > communicate via remoting. Because it takes some time for the service
to
> >> > startup some controls are added to the form when a certain event is
> > raised
> >> > by the service.
> >> >
> >> > However, when handling this event I do the following:
> >> >
> >> > --------- snip ---------
> >> >
> >> > private void EventProxy_Initialized(object sender, EventArgs e)
> >> > {
> >> > MethodInvoker invoker = new
> >> > MethodInvoker(this.CreateCommunicatorControls);
> >> > this.Invoke(invoker);
> >> > }
> >> >
> >> > private void CreateCommunicatorControls()
> >> > {
> >> > // create controls and add them to a panel on the form
> >> > this.panelCommunicator.Controls.Add(newCommCtrl);
> >> > [...]
> >> > }
> >> >
> >> > --------- snip ---------
> >> >
> >> > The panel on the form is created from the main UI thread of the
form.,
> > but
> >> > I
> >> > still get the exception "Controls created on one thread cannot be
> > parented
> >> > to controls on a different thread" when adding the new control to the
> >> > panel.
> >> >
> >> > Does anybody know what the problem is?
> >> >
> >> > Regards,
> >> > Michael
> >> >
> >> >
> >>
> >>
> >
> >
>
>