Is the TTimer.OnTimer event handler reentrant? - delphi

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?

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.

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.

Related

delphi timer ticks faster than timer service interrupt routine

Hi I have been asked to maintain a Delphi 5 based program for someone, and the program is using a timer object to tick every 50 milli-seconds and upon each time-up it runs the block of single threaded code. I am just wondering, what would happen if the time taken to execute this block of code is longer than the timer tick interval, would this be bad? For example could it cause problems like access violation? How does Delphi handle this kind of situation by default? Thanks a lot.
The critical part of this question is :
... what would happen if the time taken to execute this block of code is longer than the timer tick interval, would this be bad?
It's not great, but it's not a show stopper and it certainly cannot cause access violations. Delphi's TTimer is implemented using the WinAPI SetTimer function.
You might naively think that if your timer's handler took longer than the interval to process that the timer would continue to pile up messages in the message queue and your program would effectively lock up with a flood of timer messages that had no hope of ever all being processed. Thankfully, this isn't exactly how timers work. The documentation can shed some light.
WM_TIMER message
The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue.
Now, there isn't really a concept of "high" and "low" priority messages in a windows application, and while this statement is a little ambiguous we can take the context to mean that WM_TIMER is a message that is not posted to the application's message queue but rather generated in response to a GetMessage or PeekMessage call when a timer has been set with SetTimer, when that timer's interval has elapsed, and when there are no other messages already in the queue.
So, while the timer interval may elapse during your handler's processing, any other messages that come in while this is happening will still enter the queue normally and will be processed once your handler completes. Only once the queue has been emptied again will another WM_TIMER message be generated.
The timer events, therefore, will execute either at the rate of the tick interval or as fast as your application can process them, whichever ends up being longest. If you do have timer messages coming in too quickly, however, and your timer handler's processing time is long then your application's responsiveness can suffer. It won't become unresponsive, but all other message processing will be restricted to being processed at the interval of your timer's event handler execution time. This can make your application feel sluggish.
Example
To demonstrate, create a new forms application and add a TTimer component with an interval set to 10. Then attach this handler :
procedure TForm1.Timer1Timer(Sender: TObject);
begin
sleep(200);
end;
While the program is running, try moving the window around. What we have done is to essentially quantize the application's message processing to a 200ms interval (the duration of the timer's event handler execution).
Ticks of the timer do not interrupt your code.
Timer ticks are delivered in the form of window messages. Window messages can only arrive when you check the message queue for new messages. That happens automatically when your timer event handler returns and your program resumes its event loop, but you can trigger it explicitly by calling Application.ProcessMessages. Don't call that, though; it seldom solves problems in the long run.
If you don't check the message queue in your timer-tick handler, then your handler will never start running a second time while it's still handling a previous tick.
Even if you do check the queue, all that happens is that the tick handler will be called recursively. After all, it's all running in a single thread. Recursive timer handling probably isn't what you want to happen, though, so I'll again counsel against checking for messages in a message handler.
Furthermore, timer messages can never "pile up" if your timer handler takes a long time to run. Timer messages are "fake" in that they don't actually get added to the message queue at regular intervals. Instead, the OS will synthesize a timer message at the time your program checks the queue for more messages. If there are no higher-priority messages in the queue, and the timer interval has elapsed, then the OS will return a wm_Timer message. If you don't check for more messages, then there will be no timer message in the queue. In particular, there will not be multiple timer messages in the queue.
Further reading:
Stack Overflow: How does the message queue work in Win32?
Dr. Dobbs: Inside the Windows Messaging System

Delphi Service to Listen to TCP or UDP

Reading this question:
Delphi Windows Service Design, I saw that most designer use this code below in the OnExecute of the TService or in the TThread method, in order to keep service alive.
while not Terminated do
begin
// do something
end;
But what if I need (and I do) to create a service to respond (using Indy) to messages sent by the main application in order to send back some authentication data, what do I do with this code, ignore it or put some Sleep() in it?
Indy's TIdTCPServer and TIdUDPServer components are multi-threaded, so you don't really need to use the TService.OnExecute event at all. You could just activate them in the TService.OnStart event and deactivate them in the TService.OnStop event, and then assign handlers to the TIdTCPServer.OnExecute and TIdUDPServer.OnUDPRead events as needed. Both events are already looped for you, so you don't need a while not Terminated loop in them. Just read/process one request as needed, then exit, and wait for the next event to repeat. Let the server handle any exceptions that are raised. And keep in mind that TIdUDPServer has a ThreadedEvent property that is False by default, so you should set it to True inside a service.

Accessing DOM APIs in Firefox extension

I am writing a Firefox extension, which is doing two things (for the context of this question):
Registering for certain DOM events, viz DOMContentLoaded and DOMFrameContentLoaded.
In the call back for the events, access the DOM APIs and do certain operations.
The extension gets the first event (either DOMContentLoaded or DOMFrameContentLoaded), and the callback function invokes some DOM APIs. I am observing, before the call returning back to my extension from the DOM API call, another event firing and my call back function getting invoked (I haven't been able to narrow down which specific DOM API, as my extension invokes bunch of DOM APIs).
Is this even possible? BTW, I am on Firefox 12 on Windows. I am printing the threadManager.isMainThread, and in both situations the event call back is being invoked on the main thread.
Any pointers will be highly appreciated.
JavaScript is generally single-threaded. However, this doesn't mean that functions cannot be reentered (a function calling itself being the most obvious example). So an event handler could still be called while another event handler is executing. AFAICT this can happen under the following conditions:
The event handler causes (directly or indirectly) another event to be generated and dispatched. In particular, DOM manipulations will cause mutation events - the processing of such events happens synchronously. E.g. calling element.setAttribute() will create DOMAttrModified event and that event will be processed before element.setAttribute() returns, including running event handlers.
The event handler is "paused". This will typically happen if a modal dialog (like alert()) is opened - the current event handler will wait for this dialog to be closed while other event handlers can still be triggered. A less common case is the usage of the yield keyword in generators.
The event handler calls nsIThread.processNextEvent(). This call might execute event handlers associated with the next event in the queue. Technically, this point is the same as the one before it - alert() will call nsIThread.processNextEvent() internally to ensure that events are processed while the caller is blocked.

Threading, com+ calls with SendMessage messaging

I have an app which creates a thread which communicate with the main UI via windows messages. It simply send the message to the main app thread and received the status.
That way I am displaying modal windows and do other things.
The problem is when I have to display a form which makes a call to a com+ server.
That way I get OLE error 8001010D: An outgoing call cannot be made since the application is dispatching an input synchronous call.
I think it happens because primary SendMessage is in use and com+ calls need windows messaging for its tasks.
Anyway, In delphi I cannot display the form from a thread, but how Could I workaround the problem ... ?
Thanks
EDIT:
MAIN(UI) 2. A THREAD
A. A Thread(2) sends message to a main thread (1)
B. Main thread(1) receives the msg and before letting it come back to a thread
it displays the window.
C. The modal window in main thread wants to make a com+ call, the above error occurs.
What thread the modal window is in? 2. Which thread the COM call goes from? 3. Which thread the COM object was instantiated in? 4. Is the background thread initialized with an STA? 5. Is the modal form being shown from a SendMessage handler? – Roman R. 2 mins ago
MAIN
MAIN
MAIN
CoInitializeEx(nil, COINIT_MULTITHREADED);
yes.
The problem cause comes from inability of COM to marshal an outgoing COM call while processing SendMessage request. The error which comes up is RPC_E_CANTCALLOUT_ININPUTSYNCCALL (0x8001010D), which you are referring to. I was under impression that this only applies to SendMessage calls which are a part of incoming interthread COM requests, however this might have been a false assumption.
Your typical workaround would be to replace your SendMessage with PostMessage followed by waiting for synchronization object, event or semaphore. This way your caller background thread does not hold messaging to synchronize the calls and waits autonomously, on the main thread the message being dispatched through regular message queue and eventually reaches the same handler.
As a bonus, you have an option to safely terminate the background thread. If currently it's being locked by SendMessage API waiting for modal dialog, the suggested change would let you signal the synchronization object from the main thread and let it keep running, e.g. if you want to safely terminate it.
An alternate solution might be to call InSendMessage function and if true - defer modal UI, e.g. by again posting a message to self to pop the form up in another message handler later.

How to add a method to the message queue of the UI thread in actionscript?

I have a method that I want to be enqueued to the UI thread message pump. How is this done in actionscript? Basically I am looking for the equivalent of System.Windows.Deployment.Current.Dispatcher.BeginInvoke() in actionscript.
All timing in the Flash Player eventually comes back to the frame rate.
Not knowing exactly what the windows API you mention does, I can only assume it sets up a method to be run at a later point (say when needed by the UI, or when the UI is about to refresh).
If that's the case then you can simply setup your method to be run on the next ENTER_FRAME or EXIT_FRAME event. In both cases you need a DisplayObject to tap into (the stage is fine). There is no built-in one-shot event subscription in AS3 at this time, so you'll need to have a stub method that runs the function you want run and then removes the event listener.
You can also instantiate a Sprite, store it in a member variable and attach the event listener to it. It does not need to be on the stage for it to receive the ENTER_FRAME event.

Resources