views:

209

answers:

2

I have a TTimer in my application that fires every 2 seconds and calls my event handler, HandleTimerEvent(). The HandleTimerEvent() function modifies shared resources and can take 10's of seconds to execute before returning. Furthermore, I call Sleep() in the event handler to relinquish the processor at times.

I'm not sure how C++ builder's TTimer object works when it comes to calling events, so the scenario I just explained has got me thinking, particularly, whether HandleTimerEvent() gets called before a prior call has returned.

The question comes down to a couple of things.

Does the TTimer object queue the events?

Can the TTimer object call my event handler before a prior call has returned?

+18  A: 

This reply assumes that TTimer is still implemented to use WM_Timer messages. If the implementation has changed (since 2005), please disregard.

No, the TTimer object does not queue events. It is driven by the Windows WM_Timer message, and Windows does not let WM_TIMER messages stack up in the message queue. If the next timer interval occurs and Windows sees that a WM_Timer message is already in the app's message queue, it does not add another WM_Timer messsage to the queue. (Same for WM_Paint, btw)

Yes, it is possible for a TTimer.OnTimer event to be fired even while a prior event handler is still executing. If you do anything in your event handler that allows the app to process messages, then your timer event can be reentered. The obvious one is if your event handler calls Application.ProcessMessages, but it can be much more subtle than that - if anything you call in your event handler internally calls Application.ProcessMessages, or calls PeekMessage/GetMessage + DispatchMessage, or opens a modal dialog, or calls a COM interface that is bound to an out-of-process COM object, then messages in your app message queue will be processed and that could include your next WM_Timer message.

A simple solution is to disable the timer object when you enter your timer event handler, and reenable it when you exit your timer event handler. This will prevent timer messages from firing while your event handler is still working, regardless of the message handling characteristics of your code.

dthorpe
+1 for disabling the timer. To demonstrate the effectiveness of disabling the timer (or an easy demonstration of what can go wrong if you don't), show a messagebox in the timer handler. If you don't disable the timer upon entry, the messageboxes will stack up.
Chris Thornton
You can also use a boolean flag to prevent reentrancy in the timer event handler, but disabling the timer itself is much simpler.
dthorpe
A: 

I use TTimer extensively. It does not queue events. If you want it to hand off to an event handler, then create a TThread that handles your events so the Timer can continue with it's work. The timer does not operate asychronously but rather synchronously.

0A0D