Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Invalidate() doesnt work as expected when called from within OnTimer()

158 views
Skip to first unread message

Fabian Ottjes

unread,
Feb 28, 2002, 7:27:03 AM2/28/02
to
I've got an MFC application which consists of two threads. The first thread
primarily executes the DoModal() method of a CDialog derived class. The
second thread gathers data from a hardware device attached to a serial port.
What I am trying to do is to display the data gathered in the second thread
in the dialog window of the first thread. Because the worker thread is not
supposed to miss any data from the hardware it runs on a very high priority
and the visualization thread runs on a very low priority. Whenever the
worker thread has new data ready for being displayed it signals an event.
The visualization thread has got a timer which regularly checks whether the
event is signaled and calls the Invalidate method if the event is signaled.

The problem is that at some point the visualization thread stops redrawing.
The strange thing is that my OnTimer method still gets called but the
Invalidate() call does not cause the OnPaint() method to be called. Does
anyone have a clue of why this might happen? Does anyone know how I can
prevent using a timer so that the visualization thread instantaneously
repaints whenever the worker thread has got new data and does not wait until
the timer fires?

Thanks in advance,
Fabian Ottjes


Scott McPhillips

unread,
Feb 28, 2002, 9:52:00 AM2/28/02
to

WM_PAINT is the lowest priority message, so it may be that your high
priority thread is simply taking too much time. If it is polling the
port you could (and should) restructure it to use overlapped I/O, which
is efficient - and doesn't miss messages - and can still use a very high
priority - but doesn't waste CPU cycles. The MTTTY sample application
gives an example.

The best approach for updating the visual thread is to post a
user-defined message to it from the I/O thread. There is an example in
http://www.mvps.org/vcfaq/mfc/index.htm

--
Scott McPhillips [VC++ MVP]

Ruben Jönsson

unread,
Mar 1, 2002, 4:19:14 AM3/1/02
to
Does it work if you lower the priority of the serial port thread. I don't think you need a
high priority for serial ports. They are handled by interrupts, are buffered and are
generally rather slow.

Have you tried UpdateWindow() just after the Invalidate(). GUI updating has a low priority
and isn't handled if there are other messages pending. And so are Timer messages.

Instead of using a timer you could post a user message from the serial port thread.

Ruben

Joseph M. Newcomer

unread,
Mar 3, 2002, 10:05:47 PM3/3/02
to
It seems an odd construct. Normally, a worker thread uses PostMessage to notify a GUI
thread to do the update, so the GUI thread is not blocked on an event. Timers are not even
relevant here. If you are reading as many bytes as possible from the serial port thread,
you should have fewer problems (a common problem I've found is people who read
one-byte-at-a-time from the serial port, a sure recipe for data loss). Perhaps you could
consider the timer forcing an UpdateWindow event on the main thread. Invalidate will *not*
cause OnPaint to be called; what it will cause is a situation in which OnPaint *could* be
called if the system feels like it. Note that if you do use PostMessage, the presence of a
lot of posted messages in the queue are guaranteed to cause OnPaint to fail, because it is
only sent if there is nothing in the message queue. If by "event" you mean "Posted
message" (which is different from an Event, as in CreateEvent/WaitFor[Single,
Multiple]Object[s]), then what is happening is your realtime thread is getting ahead of
the udpate. In this case, the timer message won't help because the timer event won't get
dispatched if there is anything in the queue. The correct response would be to record the
time at which the last OnPaint is done, and as every posted message is processed, the last
OnPaint time is checked. If some threshold is exceeded, you would then call UpdateWindow,
which *does* force the OnPaint, NOW!, and may solve the problem.

I would say skip the timer and use PostMessage; read my essay on worker threads on my MVP
Tips site.
joe

On Thu, 28 Feb 2002 13:27:03 +0100, "Fabian Ottjes" <Fabian...@t-online.de> wrote:

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www3.pgh.net/~newcomer
MVP Tips: http://www3.pgh.net/~newcomer/mvp_tips.htm

0 new messages