Separate threads only run with DoEvents

  • Thread starter Thread starter Charles Law
  • Start date Start date
C

Charles Law

I know I have brought this one up before, but I didn't get an answer last
time, so hopefully I will have better luck this time.

I send data out of a serial port on my main thread. I wait for a response on
a background thread. While my main thread is waiting (only 100ms) it sits in
a loop calling DoEvents and testing a flag.

The background thread looks at the incoming data, and when it recognises
something it sets a flag.

Meanwhile, the main thread sees that the flag has been set and processes the
response. All well and good.

But if I replace the call to DoEvents with Thread.Sleep(10) it doesn't work
anymore. The background thread never gets a sniff at the data. Why would
that be? I thought the point of multi-threading was that you didn't need to
'yield' to allow another thread to get processing time.

Incidentally, please feel free to criticise the overall technique I have
described. I'm not totally happy with it myself, so any suggestions are
welcome.

TIA

Charles
 
Charles,

how does the background thread receive the data. Is it somehow connected to
the message pump of the UI-Thread?

Klaus
 
Hi Klaus

It calls WaitCommEvent and then WaitForSingleObject with INFINITE as the
second parameter.

The thread that it is on is started when the port is opened, so it is always
looking for data. The thread is marked as IsBackground = True.

Charles
 
Charles Law said:
I know I have brought this one up before, but I didn't get an answer
last time, so hopefully I will have better luck this time.

I send data out of a serial port on my main thread. I wait for a
response on a background thread. While my main thread is waiting
(only 100ms) it sits in a loop calling DoEvents and testing a
flag.

The background thread looks at the incoming data, and when it
recognises something it sets a flag.

Meanwhile, the main thread sees that the flag has been set and
processes the response. All well and good.

But if I replace the call to DoEvents with Thread.Sleep(10) it
doesn't work anymore. The background thread never gets a sniff at the
data. Why would that be? I thought the point of multi-threading was
that you didn't need to 'yield' to allow another thread to get
processing time.

Incidentally, please feel free to criticise the overall technique I
have described. I'm not totally happy with it myself, so any
suggestions are welcome.



As the docs to WaitForSingleObject say, you must process the
windows messages if you've got a UI thread. Otherwise "use
MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than
WaitForSingleObject"


--
Armin

How to quote and why:
http://www.plig.net/nnq/nquote.html
http://www.netmeister.org/news/learn2quote.html
 
Charles,

see Armins reply.

Klaus

Charles Law said:
Hi Klaus

It calls WaitCommEvent and then WaitForSingleObject with INFINITE as the
second parameter.

The thread that it is on is started when the port is opened, so it is always
looking for data. The thread is marked as IsBackground = True.

Charles
 
Hi Armin

My receive thread does not have a UI. Do you mean that I still have to use
MsgWaitForMultipleObjects? I don't see how that will help. Doesn't that just
mean that the call to MsgWaitForMultipleObjects will return when there is a
Windows message to process? If so, it will terminate for a reason other than
data being received.

Charles
 
Charles Law said:
Hi Armin

My receive thread does not have a UI. Do you mean that I still have
to use MsgWaitForMultipleObjects? I don't see how that will help.
Doesn't that just mean that the call to MsgWaitForMultipleObjects
will return when there is a Windows message to process? If so, it
will terminate for a reason other than data being received.

Maybe WaitCommEvent makes the thread an UI thread. ;-) No, I don't know.
There's nothing connected to my serial port, so I can't help you here. :)


--
Armin

How to quote and why:
http://www.plig.net/nnq/nquote.html
http://www.netmeister.org/news/learn2quote.html
 
Hi,

Are you sure your background thread is, in fact, a thread? Using
Thread.Sleep should work, if so. I have written test code that works using
this technique.

However.. There are better designs. If you simply want to wait, why not
Invoke an asynchronous delegate (this still is a thread, just of a different
feather). When then, the calling code will wait (forever, potentially)
until the delegate finishes. The delegate should have a built-in timeout,
so that it doesn't block the calling code if there is a failure to receive
the expected return data. Other UI elements will not be affected by the
call to the delegate.

Or, you can do what I prefer to do in certain designs, and that is to raise
an event from my thread, which notifies me when it is ready to return data.

If your design is a common state-machine: Send a command, Wait for a
response, then the Asynchronous Delegate approach really stands out. If
your design is more complex, where the thread may want to return a variety
of data at arbitrary times, then a free thread, event mechanism makes sense.
IMO.

The basic problem with waiting for some arbitrary amount of time is that you
always guess on the long side. Thus, your code is not as responsive as it
might be.

BTW, DoEvents is/are not a bad thing, though it/they can cause side effects
(and often should be coupled with Sleep, anyway). None-the-less, .NET
provides more efficient ways that DoEvents loops, so it behooves us to use
them for robust designs.

Dick
--
Richard Grier (Microsoft Visual Basic MVP)

See www.hardandsoftware.net for contact information.

Author of Visual Basic Programmer's Guide to Serial Communications, 3rd
Edition ISBN 1-890422-27-4 (391 pages) published February 2002.
 
Hi Dick

You make the kind of suggestions that set me thinking. I think I should look
closer at asynchronous delegates.

My scenario is actually not complicated. I have a polling thread, that sends
messages and expects a response for each message. The process must be
synchronous because this is how the receiving end operates. Data can change
with each poll, so the faster I can send and receive a message the smoother
the effect at the UI (although the polling thread is not the same as the UI
thread, data is processed and passed to the UI thread).

The user can also interact with the application in such a way that messages
are sent to the receiving end and the response is displayed on-screen.

So, I actually have three threads running: UI (main), polling, and reading
data from comms.

The reading data thread raises an event to the UI or polling thread
(whichever sent the message) whereupon the response is processed.

Because of the synchronous nature of the receiver, I have to wait before I
can send another message out. And I have to wait for a response so that I
can update the UI.

From this description, does 'asynchronous delegate' sound like a good
candidate? If presume that when the calling code invokes the delegate, the
problem of waiting is then shifted to the delegate. What method would the
delegate use for waiting? It seems to me that somewhere - even if it is in
the delegate - there has to be a loop that tests for some event, and exits
when the event occurs, or a timeout occurs.

Do you have a simple example of an asynchronous delegate that I could adapt
for my scenario? In particular, I am interested in your suggestion that
".NET provides more efficient ways than DoEvents loops". Could you
elaborate?

Thanks.

Charles
 
Back
Top