About BeginInvoke/ThreadPool/Threading

F

FP

Hi,
i'm currently developing a class to communicate with a serial device,using
the SerialPort component.
Basically,the main application will interact with this class through its
method "Call",the class itself will handle all the details of a call (AT
commands included).
My problem is that i dont want the application to hang while i'm
interacting with the modem,so i have started to learn about threading.

Many people have suggested me to use BeginInvoke/EndInvoke,which relies on
pooled threads,but i just found out in some articles that author suggests
not to use pooled threads for tasks that lasts more than few seconds,which
is not my case (it might last some minutes).
Now i wonder: does this advice apply only when my application spawns many
threads? I.e. is the thread pool shared with other processes,so i have to
worry about not blocking other processes' thread pools?

So far i'm not yet sure whether to use the BeginInvoke/EndInvoke or create
a new thread,since after all my modem is a finite state machine,and i was
thinking to events as the way to signal state transitions to the main
application.Which approach would you suggest?

Thanks in advance :)
 
J

Jon Skeet [C# MVP]

i'm currently developing a class to communicate with a serial device,using
the SerialPort component.
Basically,the main application will interact with this class through its
method "Call",the class itself will handle all the details of a call (AT
commands included).
My problem is that i dont want the application to hang while i'm
interacting with the modem,so i have started to learn about threading.

Many people have suggested me to use BeginInvoke/EndInvoke,which relies on
pooled threads

That depends which BeginInvoke/EndInvoke they're talking about.
Control.BeginInvoke/Control.EndInvoke don't use threadpool threads,
but Delegate.BeginInvoke/Delegate.EndInvoke do.

Now i wonder: does this advice apply only when my application spawns many
threads? I.e. is the thread pool shared with other processes,so i have to
worry about not blocking other processes' thread pools?

No, there's one thread pool per process.
So far i'm not yet sure whether to use the BeginInvoke/EndInvoke or create
a new thread,since after all my modem is a finite state machine,and i was
thinking to events as the way to signal state transitions to the main
application.Which approach would you suggest?

If your task is going to last quite a while, the overhead of creating
a new thread will be insignificant. Just remember that you need to
marshal back over to the UI thread (e.g. with Control.BeginInvoke)
before updating the UI.

Jon
 
F

FP

Jon said:
If your task is going to last quite a while, the overhead of creating
a new thread will be insignificant. Just remember that you need to
marshal back over to the UI thread (e.g. with Control.BeginInvoke)
before updating the UI.

Thanks Jon :) (by the way,i'm reading your article about multithreading in
..NET right now!)

I ask now a million dollar question :)
Which approach would be better in my case? Or,in other terms,what should i
worry about,before choosing the approach? So far,i couldn't find any
resource which could help me making this decision (probably because i'm a
complete newbie to threading and also a newbie to programming :) ).

I (think i) won't actually need many threads,but just one to avoid
bothering the GUI of the app,but i also would like to signal to the main
app about the progress of the call (i will have a progress bar there):so i
think i will have to fire events from my class (is that the right
approach?) when state changes.
This event strategy applies without any distinction both if i use the new
thread approach and the asynchronous methods one?

As you can see i'm still in a preliminary stage,and i still have to learn
MANY things,but an "enlightened" advice would help me a lot :)

Thanks in advance :)
 
J

John Duval

Hi,
i'm currently developing a class to communicate with a serial device,using
the SerialPort component.
Basically,the main application will interact with this class through its
method "Call",the class itself will handle all the details of a call (AT
commands included).
My problem is that i dont want the application to hang while i'm
interacting with the modem,so i have started to learn about threading.

Many people have suggested me to use BeginInvoke/EndInvoke,which relies on
pooled threads,but i just found out in some articles that author suggests
not to use pooled threads for tasks that lasts more than few seconds,which
is not my case (it might last some minutes).
Now i wonder: does this advice apply only when my application spawns many
threads? I.e. is the thread pool shared with other processes,so i have to
worry about not blocking other processes' thread pools?

So far i'm not yet sure whether to use the BeginInvoke/EndInvoke or create
a new thread,since after all my modem is a finite state machine,and i was
thinking to events as the way to signal state transitions to the main
application.Which approach would you suggest?

Thanks in advance :)

Hi FP,
The thread pool (and threads in general) are not shared with other
processes; a thread is owned by one process only. So you do not have
to worry about blocking other processes. Unless your process is
likely to use the thread pool for other reasons, I think it's fine to
have your operations run on the thread pool threads. If you start
having a lot of these operations running concurrently (and consuming
lots of threads for a long time), you might run out of threads in the
threadpool, but it doesn't sound like your app is likely to do this.

John
 
J

Jon Skeet [C# MVP]

Thanks Jon :) (by the way,i'm reading your article about multithreading in
.NET right now!)

I ask now a million dollar question :)
Which approach would be better in my case? Or,in other terms,what should i
worry about,before choosing the approach? So far,i couldn't find any
resource which could help me making this decision (probably because i'm a
complete newbie to threading and also a newbie to programming :) ).

If your task is going to last a long time, I'd just go with starting a
new thread. It's really not that expensive.
I (think i) won't actually need many threads,but just one to avoid
bothering the GUI of the app,but i also would like to signal to the main
app about the progress of the call (i will have a progress bar there):so i
think i will have to fire events from my class (is that the right
approach?) when state changes.

Firing events is fine - but be aware that the event will still be
raised on the worker thread. You'll still need to marshal it over to
the UI thread yourself.
This event strategy applies without any distinction both if i use the new
thread approach and the asynchronous methods one?

Yup - although with the ThreadPool you could use BackgroundWorker
which makes life a bit easier.
As you can see i'm still in a preliminary stage,and i still have to learn
MANY things,but an "enlightened" advice would help me a lot :)

I don't know about enlightened, but I hope that helps :)

Jon
 
C

Chris Mullins [MVP - C#]

FP said:
Many people have suggested me to use BeginInvoke/EndInvoke,which relies on
pooled threads,but i just found out in some articles that author suggests
not to use pooled threads for tasks that lasts more than few seconds,which
is not my case (it might last some minutes).
[...] Which approach would you suggest?

For I/O bound tasks, Async I/O is the answer. I'm not familiar enough with
modem communication under .Net to know if it has all the BeginSend /
BeginReceive methods, but if those are present, it would likley be the best
way to go.

If the Modem infrastructure doesn't support this, then creating your own
threads is the answer...
 
F

FP

Hi,
after some deeper investigations i found out that received data are treated
in a separate thread,so i am beginning to wonder if i might really need to
create a new thread.I will better explain my application,now.

I have created a wrapper class (called USBModem) around the SerialPort
class.
The class has a public CallRemoteModem method,which starts the call
"procedure",composed of the following steps:
1)Check if modem is connected
2)Check if the signal strength is good
3)Call the remote modem

Inside the class i have an event handler for the SerialPort.DataReceived
event. This event is fired on a separate thread (i have read somewhere that
this thread operates on the threadpool), whenever data is received on the
port.This is done by the SerialPort object.
In the DataReceived event I collect received characters in a buffer until I
have a complete message:at that time i will fire a "ResponseComplete"
event.

Each step of the call procedure is actually simply writing an AT command to
the output buffer.I was thinking to handle all of this with events,
implementing the following scheme:

1-CheckModemConnection (actually a method which actually writes only "AT"
to the output buffer)

2-Wait for the received message to be complete

3-When received message is complete and correct, Check the signal (actually
writing another string to the output buffer)

4-Fire a "Step2Began" to inform main app of the state transition

5-Wait for the received message to be complete

6-When received message is complete and correct Call the remote modem (of
course,writing another string to the output buffer)

7-Fire a "CallBegan" to inform main app of the state transition

8-Wait for the received message to be complete (this step can be very long)

9-Analyze the result of the call


What suggested me to create a new thread is the fact that step8 can last
some minutes,but now,knowing that DataReceived is on another thread is
making me wonder....
Will the main app hang while i'm receiving the string from the remote
modem?
Obviously i will have to test (but i can't right now),but the fact that
DataReceived is already running on a separate thread is kinda confusing
me....
 
P

Peter Duniho

Hi,
after some deeper investigations i found out that received data are treated
in a separate thread,so i am beginning to wonder if i might really need to
create a new thread.I will better explain my application,now.

I think that for sure, you do not need to create a new thread. But
that's not to say that you can also just spend a long time reading data
from the SerialPort.
[...]
What suggested me to create a new thread is the fact that step8 can last
some minutes,but now,knowing that DataReceived is on another thread is
making me wonder....
Will the main app hang while i'm receiving the string from the remote
modem?

Not immediately, no. But depending on what thread pool is actually
being used for raising the DataReceived event, you could cause some
problems if you tie up a thread from the pool for a lengthy period of
time.

In most cases, the likelihood of a problem is low, but it does exist.
Obviously i will have to test (but i can't right now),but the fact that
DataReceived is already running on a separate thread is kinda confusing
me....

IMHO, you have a couple of options:

* Use the DataReceived event
* Use the SerialPort.BaseStream and use the async methods of that
stream (this is basically what Chris Mullins is suggesting)

I would ordinarily agree with Chris and suggest using the BaseStream.
This would involve calling Stream.BeginRead, and then in your callback
processing the data that's been read (retrieved by calling
Stream.EndRead) and calling Stream.BeginRead again.

The thing that gives me pause is that in the SerialPort docs, it says
that the base stream is not buffered, while the SerialPort class itself
is. I would be concerned that you could potentially lose data if you
aren't careful with how you use the BaseStream, by not having an
outstanding read posted when some data comes in.

Granted, it could be I'm just misunderstanding the implementation. I
don't really know much about SerialPort or of the Stream that it uses,
and it's possible that the docs are being misleading by saying that the
stream isn't buffered (they could be talking about some kind of buffer
other than at the lowest level, for example).

Basically, while I think you ought to be able to use the Stream
methods, the docs make me wonder about that, and it seems like the
DataReceived event should provide a similar enough behavior to be
sufficient.

So, how to use DataReceived? You should not spend any significant time
in your DataReceived handler. You should read whatever bytes are
available, appending them to some buffer somewhere. If and when that
buffer represents a complete transmission, then you do whatever
processing is appropriate for a completed transmission.

Basically, just let the SerialPort raise that event repeatedly until
you've received all of the data you need. Don't do any waiting in any
thread for data per se, other than the normal waiting that occurs in
any application (waiting for user input via the normal Windows event
mechanism, for example).

Pete
 

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