Can a thread only be a method?

S

Sin Jeong-hun

I've using thread a lot in C#, but all of them were just single method
with no return value or paramenters. It may sound bizarre but, can't
it be a class?

I'm writing an Windows application that processes inputs from a serial
port. The serial port data is processed when DataReceived event occurs
from the SerialPort instance. If the DataReceived event handler and
the MainForm are in the same thread, and the user is calling a method
in the Mainform which possibly take a few seconds, and if data is
received at that time, I worry that event might not be handled. So I
want to run serial port handler class in a separate thread but all I
know is to run a method as a thread.

//A method that takes 5 seconds
void OnMenuClicked(object sender, EventArgs e)
{
//Now 00:00:00
doing some work.....
//Now 00:00:05
}

void SerialPort_DataReceved(....)
{
//If this happend at 00:00:02, would it be processed?
}

If running a class as a separate class is a stupid idea, what should I
do to ensure the DataReceived events be processed properly even if the
MainForm is busy?

Thank you very much.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Sin said:
I've using thread a lot in C#, but all of them were just single method
with no return value or paramenters. It may sound bizarre but, can't
it be a class?

A thread executes code. Code has to be in a method. A method has to be
in a class.
I'm writing an Windows application that processes inputs from a serial
port. The serial port data is processed when DataReceived event occurs
from the SerialPort instance. If the DataReceived event handler and
the MainForm are in the same thread, and the user is calling a method
in the Mainform which possibly take a few seconds, and if data is
received at that time, I worry that event might not be handled. So I
want to run serial port handler class in a separate thread but all I
know is to run a method as a thread.

//A method that takes 5 seconds
void OnMenuClicked(object sender, EventArgs e)
{
//Now 00:00:00
doing some work.....
//Now 00:00:05
}

void SerialPort_DataReceved(....)
{
//If this happend at 00:00:02, would it be processed?
}

If running a class as a separate class is a stupid idea, what should I
do to ensure the DataReceived events be processed properly even if the
MainForm is busy?

Separate thread running a method - possible updating the form
via Invoke.

Arne
 
B

Bruce Wood

I've using thread a lot in C#, but all of them were just single method
with no return value or paramenters. It may sound bizarre but, can't
it be a class?

I'm writing an Windows application that processes inputs from a serial
port. The serial port data is processed when DataReceived event occurs
from the SerialPort instance. If the DataReceived event handler and
the MainForm are in the same thread, and the user is calling a method
in the Mainform which possibly take a few seconds, and if data is
received at that time, I worry that event might not be handled. So I
want to run serial port handler class in a separate thread but all I
know is to run a method as a thread.

//A method that takes 5 seconds
void OnMenuClicked(object sender, EventArgs e)
{
//Now 00:00:00
doing some work.....
//Now 00:00:05

}

void SerialPort_DataReceved(....)
{
//If this happend at 00:00:02, would it be processed?

}

If running a class as a separate class is a stupid idea, what should I
do to ensure the DataReceived events be processed properly even if the
MainForm is busy?
From the documentation:

"The DataReceived event is raised on a secondary thread when data is
received from the SerialPort object. Because this event is raised on a
secondary thread, and not the main thread, attempting to modify some
elements in the main thread, such as UI elements, could raise a
threading exception. If it is necessary to modify elements in the main
Form or Control, post change requests back using Invoke, which will do
the work on the proper thread."

In other words, your SerialPort_DataReceived event is _always_ called
on a secondary thread. You don't have a choice in the matter. So, it
can _never_ be blocked by UI activity.

The real question is how to make changes to your user interface
(Controls) as a result of what is received from the serial port. The
doc tells you one way (although not the only way) to do that.
 
S

Sin Jeong-hun

"The DataReceived event is raised on a secondary thread when data is
received from the SerialPort object. Because this event is raised on a
secondary thread, and not the main thread, attempting to modify some
elements in the main thread, such as UI elements, could raise a
threading exception. If it is necessary to modify elements in the main
Form or Control, post change requests back using Invoke, which will do
the work on the proper thread."

In other words, your SerialPort_DataReceived event is _always_ called
on a secondary thread. You don't have a choice in the matter. So, it
can _never_ be blocked by UI activity.

The real question is how to make changes to your user interface
(Controls) as a result of what is received from the serial port. The
doc tells you one way (although not the only way) to do that.

Thank you. Till .NET 1.1, I could access the UI objects within
separate threads,
but with .NET 2.0, this caused InvalidOperationException. I was aware
of
this problem since I migrated to the .NET 2.0, so I know how to handle
this
using delegates and Invoke.

I mainly use C#, but for this project I'm actually using VB.NET. Since
VB.NET
and C# use the same base class library, I asked this question here.
(I'm sorry if
you think it was wrong) I added SerialPort WithEvents to the MainForm
and
accessed UI objects (TextBox.AppendText() to be exact)
within SerialPort_DataReceived, but it didn't cause
InvalidOperationException.
So I thought that SerialPort_DataReceived method was running on the
same
thread as the MainForm. Maybe that was VB.NET specific, I guess I have
to
try the same code in C#.

Thank you, Mr. Bruce Wood.
 
B

Bruce Wood

Thank you. Till .NET 1.1, I could access the UI objects within
separate threads,

Well, you could and you couldn't. You could, but it would cause random
cross-threading errors. The docs tell you not to, and if you do it in
1.1 it _will_ occasionally crash your app. However, many people didn't
know this because they did it anyway and it often worked.
but with .NET 2.0, this caused InvalidOperationException. I was aware
of this problem since I migrated to the .NET 2.0, so I know how to handle
this using delegates and Invoke.

Invoke is one way to handle the problem. The other way (which may be
better in your case) is a neutral data structure accessed from both
threads. See below for more info.
I mainly use C#, but for this project I'm actually using VB.NET. Since
VB.NET
and C# use the same base class library, I asked this question here.
(I'm sorry if
you think it was wrong) I added SerialPort WithEvents to the MainForm
and
accessed UI objects (TextBox.AppendText() to be exact)
within SerialPort_DataReceived, but it didn't cause
InvalidOperationException.
So I thought that SerialPort_DataReceived method was running on the
same
thread as the MainForm. Maybe that was VB.NET specific, I guess I have
to
try the same code in C#.

No, it's not VB specific. The Framework is language-neutral, so if you
believe the docs then DataReceived is always called on a non-UI
thread, and you should always marshal back onto the UI thread in order
to update the UI.

There is one simple way to tell whether your method is running on a
secondary thread: Simply write to a log file the value of some
control's InvokeRequired property. If it's true (it should be) then
you're running on a non-UI thread. You can always try popping a
MessageBox containing the value, but then this may crash your app. :)

Invoke is one way to get back onto the UI thread, but in your case it
may cause a problem. Depending upon how often you're getting those
DataReceived events, you may overload the UI thread with invoke
requests. You see, all Invoke really does is package up a method call
in a data structure and queue it to be processed later on the UI
thread, where "queue it" means, literally, sticking the data structure
on a queue in memory, where the UI thread will grab it later in order
to actually call the method.

If you Invoke onto the UI thread faster than the UI thread can pick
those requests off the queue and call the invoked method, then the
queue just keeps getting bigger and bigger and the UI farther and
farther behind the serial port. If you're receiving an event every
second or so, it's probably OK, but if you're receiving 100 or even 10
events a second, you may have problems.

Another possible solution is a neutral data structure: your
DataReceived method updates a data structure, and your UI then polls
that data structure from time to time and updates the UI with changes.
No Invoke required: the DataReceived method writes to the data
structure, and the UI reads it. The only thing you have to do is take
out a lock on the data structure while reading and writing to ensure
that one isn't reading while the other is writing.

So, there you have it: two possible solutions, depending upon your
situation.
 
C

Chris Mullins [MVP]

Sin Jeong-hun said:
I've using thread a lot in C#, but all of them were just single method
with no return value or paramenters. It may sound bizarre but, can't
it be a class?

It's easy enough to tie a thread to a class - in fact languages like Java
require just this (IIRC).

This is very easy to do in C#:

public class Foo
{
private Thread _t;
public Foo()
{
_t = new Thread(startup);
_t.start();
}
private void Startup()
{
// Now we're in a method in the class. Can do anything here...
}
}

(This code is psudo code - I just typed it in here...)
 
C

Chris Mullins [MVP]

Sin Jeong-hun said:
I'm writing an Windows application that processes inputs from a serial
port. The serial port data is processed when DataReceived event occurs
from the SerialPort instance. If the DataReceived event handler and
the MainForm are in the same thread, and the user is calling a method
in the Mainform which possibly take a few seconds, and if data is
received at that time, I worry that event might not be handled. So I
want to run serial port handler class in a separate thread but all I
know is to run a method as a thread.

You actually don't want to really use custom threads for this - you're
better off using Asynchronous I/O.

If you poke around the methods that you're calling, you'll find a
"BeginRead(..)" method in there. Look that up in the help, and figure out
how to take advantage of it. That's really the best way for you to be doing
I/O from the Serial Port...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top