Home All Groups Group Topic Archive Search About

Newbie question: Thread access of form components

Author
9 Jun 2005 8:32 PM
Don Tucker
I'm just getting familiar with Visual Studio and C#.  I want to start a
thread that monitors a serial port and sends what comes across to a text box
on the main screen.  So, I create a thread to do that at the push of a
button.  However, when something comes in on the serial port, the program
bombs because it says that I am trying to access a component (namely, the
textBox) that was created in another thread.  I tried calling
Monitor.Enter(textBox1) and Monitor.Exit(textBox1) before and after the
textBox1.Text = ... call, but still get the same error.  Can someone give me
a tiny example of how to access a component on the main form from within a
thread?

Thanks,
Don

Author
9 Jun 2005 9:18 PM
Lebesgue
use Invoke() method on the Control.

Show quoteHide quote
"Don Tucker" <Don Tuc***@discussions.microsoft.com> wrote in message
news:4C6A26FB-8B1F-4F0E-B67C-07512FDAC062@microsoft.com...
> I'm just getting familiar with Visual Studio and C#.  I want to start a
> thread that monitors a serial port and sends what comes across to a text
box
> on the main screen.  So, I create a thread to do that at the push of a
> button.  However, when something comes in on the serial port, the program
> bombs because it says that I am trying to access a component (namely, the
> textBox) that was created in another thread.  I tried calling
> Monitor.Enter(textBox1) and Monitor.Exit(textBox1) before and after the
> textBox1.Text = ... call, but still get the same error.  Can someone give
me
> a tiny example of how to access a component on the main form from within a
> thread?
>
> Thanks,
> Don
Are all your drivers up to date? click for free checkup

Author
9 Jun 2005 9:42 PM
Don Tucker
I'm sorry.  The documentation seems a bit sparse on Invoke.  Do you mean, 
_Activator.Invoke(textBox1,...) ?  I don't understand how to use this?

Don

Show quoteHide quote
"Lebesgue" wrote:

> use Invoke() method on the Control.
>
> "Don Tucker" <Don Tuc***@discussions.microsoft.com> wrote in message
> news:4C6A26FB-8B1F-4F0E-B67C-07512FDAC062@microsoft.com...
> > I'm just getting familiar with Visual Studio and C#.  I want to start a
> > thread that monitors a serial port and sends what comes across to a text
> box
> > on the main screen.  So, I create a thread to do that at the push of a
> > button.  However, when something comes in on the serial port, the program
> > bombs because it says that I am trying to access a component (namely, the
> > textBox) that was created in another thread.  I tried calling
> > Monitor.Enter(textBox1) and Monitor.Exit(textBox1) before and after the
> > textBox1.Text = ... call, but still get the same error.  Can someone give
> me
> > a tiny example of how to access a component on the main form from within a
> > thread?
> >
> > Thanks,
> > Don
>
>
>
Author
10 Jun 2005 8:31 AM
Cordell Lawrence
Don, the Invoke() method that you're looking for is the Invoke method of the
TextBox itself inherited from the Control class. Basically visual controls
should only be modified and methods called on the thread on which they were
created. Since most developers create new forms on the main application
thread (I believe that this is also a recomendation by MS) the Invoke method
allows you to queue up control updates on the main thread from worker
threads. It's very useful.

Check out
http://msdn.microsoft.com/msdnmag/issues/03/02/Multithreading/default.aspx
Note the "Threads and Controls" section.

Hope this helps
Cordell Lawrence
Teleios Systems


Show quoteHide quote
"Don Tucker" <DonTuc***@discussions.microsoft.com> wrote in message
news:9E5C745F-35CE-44EB-AC1A-FA2C5BF9FA4A@microsoft.com...
> I'm sorry.  The documentation seems a bit sparse on Invoke.  Do you mean,
> _Activator.Invoke(textBox1,...) ?  I don't understand how to use this?
>
> Don
>
> "Lebesgue" wrote:
>
> > use Invoke() method on the Control.
> >
> > "Don Tucker" <Don Tuc***@discussions.microsoft.com> wrote in message
> > news:4C6A26FB-8B1F-4F0E-B67C-07512FDAC062@microsoft.com...
> > > I'm just getting familiar with Visual Studio and C#.  I want to start
a
> > > thread that monitors a serial port and sends what comes across to a
text
> > box
> > > on the main screen.  So, I create a thread to do that at the push of a
> > > button.  However, when something comes in on the serial port, the
program
> > > bombs because it says that I am trying to access a component (namely,
the
> > > textBox) that was created in another thread.  I tried calling
> > > Monitor.Enter(textBox1) and Monitor.Exit(textBox1) before and after
the
> > > textBox1.Text = ... call, but still get the same error.  Can someone
give
> > me
> > > a tiny example of how to access a component on the main form from
within a
> > > thread?
> > >
> > > Thanks,
> > > Don
> >
> >
> >
Author
10 Jun 2005 8:35 PM
Don Tucker
OK. that helps a lot.  I was able to get a version of the code from Figure 3
from the linked article to work (in my case, the textBox prints "hi" every
time something comes over the serial port).  However, in order to display the
content of the serial port to the textBox, I need to get the snippet from
Figure 4 working.  There is an editor's note in the article that I don't
really understand, also the creation of MyProgressEvents and
MyProgressEventsHandler is confusion to me.

Is there a simple mod to the Figure 3 code to allow passing arguments into
the UpdateUI method?

Don

Show quoteHide quote
"Cordell Lawrence" wrote:

> Don, the Invoke() method that you're looking for is the Invoke method of the
> TextBox itself inherited from the Control class. Basically visual controls
> should only be modified and methods called on the thread on which they were
> created. Since most developers create new forms on the main application
> thread (I believe that this is also a recomendation by MS) the Invoke method
> allows you to queue up control updates on the main thread from worker
> threads. It's very useful.
>
> Check out
> http://msdn.microsoft.com/msdnmag/issues/03/02/Multithreading/default.aspx
> Note the "Threads and Controls" section.
>
> Hope this helps
> Cordell Lawrence
> Teleios Systems
>
>
> "Don Tucker" <DonTuc***@discussions.microsoft.com> wrote in message
> news:9E5C745F-35CE-44EB-AC1A-FA2C5BF9FA4A@microsoft.com...
> > I'm sorry.  The documentation seems a bit sparse on Invoke.  Do you mean,
> > _Activator.Invoke(textBox1,...) ?  I don't understand how to use this?
> >
> > Don
> >
> > "Lebesgue" wrote:
> >
> > > use Invoke() method on the Control.
> > >
> > > "Don Tucker" <Don Tuc***@discussions.microsoft.com> wrote in message
> > > news:4C6A26FB-8B1F-4F0E-B67C-07512FDAC062@microsoft.com...
> > > > I'm just getting familiar with Visual Studio and C#.  I want to start
> a
> > > > thread that monitors a serial port and sends what comes across to a
> text
> > > box
> > > > on the main screen.  So, I create a thread to do that at the push of a
> > > > button.  However, when something comes in on the serial port, the
> program
> > > > bombs because it says that I am trying to access a component (namely,
> the
> > > > textBox) that was created in another thread.  I tried calling
> > > > Monitor.Enter(textBox1) and Monitor.Exit(textBox1) before and after
> the
> > > > textBox1.Text = ... call, but still get the same error.  Can someone
> give
> > > me
> > > > a tiny example of how to access a component on the main form from
> within a
> > > > thread?
> > > >
> > > > Thanks,
> > > > Don
> > >
> > >
> > >
>
>
>
Author
9 Jun 2005 10:15 PM
PIEBALD
I've never had that problem.
Is the method the thread runs in the same class as the control?
That's how I do it.
Author
10 Jun 2005 10:23 AM
Willy Denoyette [MVP]
"PIEBALD" <PIEB***@discussions.microsoft.com> wrote in message
news:95712E98-B89B-4129-968F-7DF80AD5857B@microsoft.com...
> I've never had that problem.
> Is the method the thread runs in the same class as the control?
> That's how I do it.
>
>

And that's exactly how you should NOT do it.
A Windows application that has separate threads that update the UI, it's
only the thread that created the UI element (Control) who is allowed to
directly touch that Control, other threads must marshal the call so the
methods executes on the UI thread. The frameworks supports this marshaling
through the Control.Invoke or Control.BeginInvoke members.

Willy.
Author
10 Jun 2005 3:09 PM
PIEBALD
So I guess I'll have my other thread create the control too.

Oh, wait, what if the control spawns a thread to update itself?
Author
10 Jun 2005 5:49 PM
Jon Skeet [C# MVP]
PIEBALD <PIEB***@discussions.microsoft.com> wrote:
> So I guess I'll have my other thread create the control too.
>
> Oh, wait, what if the control spawns a thread to update itself?

It's still not the UI thread for that control. It's only the thread
which creates the control which is allowed to access it.

See http://www.pobox.com/~skeet/csharp/threads/winforms.shtml

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Author
10 Jun 2005 6:16 PM
PIEBALD
But what exactly is the problem? If it's just that you should only have one
thread doing it, then why does it matter which thread?

Also, what if I have a thread that creates controls for other threads and
then terminates? How does a control know what thread created it?
Author
10 Jun 2005 6:43 PM
Jon Skeet [C# MVP]
PIEBALD <PIEB***@discussions.microsoft.com> wrote:
> But what exactly is the problem? If it's just that you should only have one
> thread doing it, then why does it matter which thread?

Because that's the way Windows works. This isn't a .NET issue, it's a
Windows issue. (It's also the way some other windowing systems work.)

> Also, what if I have a thread that creates controls for other threads and
> then terminates? How does a control know what thread created it?

I don't know the details of exactly how it all works, but I don't think
it's worth worrying too much about it - just treat it as a given rule
to obey.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Author
10 Jun 2005 7:30 PM
Willy Denoyette [MVP]
"PIEBALD" <PIEB***@discussions.microsoft.com> wrote in message
news:FC2CF30B-3983-444D-97A2-F7F13FCB7F12@microsoft.com...
> But what exactly is the problem? If it's just that you should only have
> one
> thread doing it, then why does it matter which thread?
>

It's a rule in windows that says NOT to use a "window" handle (actualy a GDI
handle) associated with a window control from another thread than the owning
thread, simply stated Window handles have thread affinity. Most of the time
and for most actions on controls it works, but there are times it breaks in
a bad way. V2.0 of the framework includes a debug probe to guard against
this cross-thread control access and will throw an exception in debug mode.

> Also, what if I have a thread that creates controls for other threads and
> then terminates? How does a control know what thread created it?

And how is one thread going to ask another thread to create a control,  by
marshaling the call, right? so the creating thread becomes the owner of the
control, but look, a control can only be created if there is a parent window
(say the main application window) owned by the same thread, so this thread
is responsible for disposing all controls in the chain starting from the top
window when terminating.

A control doesn't know which thread is the owner, the OS knows it and an
application can ask if the current thread owns the control handle by
checking the Control.InvokeRequired property.

Willy.
Author
10 Jun 2005 9:43 PM
Don Tucker
Ah!  OK, I was finally able to get it working with the sample provided from
the link below.  Thanks for much everyone!

Don

Show quoteHide quote
"Jon Skeet [C# MVP]" wrote:

> PIEBALD <PIEB***@discussions.microsoft.com> wrote:
> > So I guess I'll have my other thread create the control too.
> >
> > Oh, wait, what if the control spawns a thread to update itself?
>
> It's still not the UI thread for that control. It's only the thread
> which creates the control which is allowed to access it.
>
> See http://www.pobox.com/~skeet/csharp/threads/winforms.shtml
>
> --
> Jon Skeet - <sk***@pobox.com>
> http://www.pobox.com/~skeet
> If replying to the group, please do not mail me too
>

Bookmark and Share