In dieser Antwort wird davon ausgegangen, dass TTimer weiterhin für die Verwendung von WM_Timer-Nachrichten implementiert ist. Wenn sich die Implementierung geändert hat (seit 2005), bitte ignorieren.
Nein, das TTimer-Objekt stellt keine Ereignisse in die Warteschlange. Es wird von der Windows WM_Timer-Nachricht gesteuert und Windows lässt WM_TIMER-Nachrichten nicht in der Nachrichtenwarteschlange aufstocken. Wenn das nächste Zeitgeberintervall auftritt und Windows erkennt, dass sich eine WM_Timer-Nachricht bereits in der Nachrichtenwarteschlange der Anwendung befindet, fügt es der Warteschlange keine weitere WM_Timer-Nachricht hinzu. (Gleiches für WM_Paint, btw)
Ja, es ist möglich, dass ein TTimer.OnTimer-Ereignis ausgelöst wird, auch wenn ein vorheriger Ereignishandler noch ausgeführt wird. Wenn Sie in Ihrem Ereignishandler etwas tun, mit dem die App Nachrichten verarbeiten kann, kann Ihr Timer-Ereignis erneut eingegeben werden. Der offensichtliche ist, wenn Ihr Event-Handler Application.ProcessMessages aufruft, aber es kann viel subtiler als das sein - wenn Sie Ihren Event-Handler aufrufen, ruft Application.ProcessMessages intern auf oder ruft PeekMessage/GetMessage + DispatchMessage auf oder öffnet einen modalen Dialog oder ruft eine COM-Schnittstelle auf, die an ein prozessexternes COM-Objekt gebunden ist, dann werden Nachrichten in Ihrer App-Nachrichtenwarteschlange verarbeitet, die Ihre nächste WM_Timer-Nachricht enthalten können.
Eine einfache Lösung besteht darin, das Timer-Objekt zu deaktivieren, wenn Sie den Timer-Event-Handler eingeben und ihn erneut aktivieren, wenn Sie den Timer-Event-Handler beenden. Dadurch wird verhindert, dass Timer-Meldungen ausgelöst werden, während der Ereignishandler noch funktioniert, unabhängig von den Eigenschaften der Nachrichtenbehandlung Ihres Codes.
+1 zum Deaktivieren des Timers. Um die Effektivität der Deaktivierung des Timers zu demonstrieren (oder eine einfache Demonstration dessen, was schief gehen kann, wenn Sie dies nicht tun), zeigen Sie eine Nachrichtenbox im Timer-Handler an. Wenn Sie den Timer bei der Eingabe nicht deaktivieren, werden die Messageboxen zusammengelegt. –
Sie können auch ein boolesches Flag verwenden, um die Rückkehr in den Timer-Event-Handler zu verhindern, aber das Deaktivieren des Timers selbst ist viel einfacher. – dthorpe
Siehe https://forums.embarcadero.com/thread.jspa?messageID=171751𩻧 für eine nützliche TTimerGuard-Klasse, eine RAII-style-Klasse für TTimer-Verwendung. Möglicherweise müssen Sie die FInterval-Nutzung abhängig von Ihrer Implementierung anpassen. –