Newbie question: Thread access of form components

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

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
 
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
 
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.
 
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
 
PIEBALD said:
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.
 
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?
 
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?
 
PIEBALD said:
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.
 
PIEBALD said:
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.
 
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
 
Ah! OK, I was finally able to get it working with the sample provided from
the link below. Thanks for much everyone!

Don
 
Back
Top