Announcement

Collapse
No announcement yet.

TTimer Event auslösen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • TTimer Event auslösen

    Hallo alle,

    ich habe ein Problem, dass meine dynamisch erzeugte TTimer-Komponente den ihr zugewiesenen OnTimer-Event nicht ausführt.

    Ich habe nur eine Watchdag-Klasse geschaffen, die einen TTimer verwendet. Die entsprechende Deklaration im Header-File ist wie folgt:

    Code:
    class TWatchdog
    {
        TTimer*   fTimer;
        void __fastcall ExecTimerHandler(TObject *Sender);
    
        private:
          AnsiString fID;       // Eindeutige ID des WD
          AnsiString fCode;     // BVFlex-Code, der nach Ablauf des WD ausgeführt werden soll
          int        fTime;     // Zeit in ms, mit der der Timer initial gestartet wurde
          bool       fRunOnce;  // Flag, ob WD einmal oder permanent ausgeführt werden soll
    
          void __fastcall SetCode(AnsiString aCode);
          void __fastcall SetTime(int aTime);
          bool __fastcall GetIsRunning(void);
    
        public:
          __property AnsiString ID = {read = fID, write = fID};
          __property AnsiString Code = {read = fCode, write = SetCode};
          __property bool RunOnce = {read = fRunOnce, write = fRunOnce};
          __property int Time = {read = fTime, write = SetTime};
    
          // read-only properties
          __property bool IsRunning = {read = GetIsRunning};
    
          // Methoden
          __fastcall TWatchdog(void);  // Konstruktor
          __fastcall ~TWatchdog(void);  // Destruktor
    
          void __fastcall Pause(void);
          void __fastcall Resume(void);
          void __fastcall Reset(void);
          void __fastcall Start(int aTime, AnsiString aCode, bool aRunOnce = true);
    };

    Im Konstruktor weise ich dann das Event zu:
    Code:
    /* ---------------------------------------------------------------------------
       Konstruktor
    
       Eingabeparameter:  keine oder Systemvorgabe
       Rückgabeparameter: keine oder Systemvorgabe
    
       2009-07-29/Zm  - Funktion erstellt
    */
    __fastcall TWatchdog::TWatchdog(void)
    {
      fTimer = new TTimer(NULL); 
      fTimer->OnTimer = ExecTimerHandler;
      fTimer->Enabled = false;
    
      fID = "";
      fCode = "";
      fTime =  1000;
      fRunOnce =  true;
    }

    Mehrere Watchdog-Objekte bündele ich in einer TWatchdogs-Klasse, was aber für mein Problem nicht relevant sein dürfte.

    Nun arbeitet mein Programm hauptsächlich mit zwei Threads, dem Mainthread (für die Anzeige) und einem weiteren Thread - meinem OperatingThread -, der einen Interpreter implementiert, der zur Laufzeit Befehle einer eigenen Skript-Sprache in C-Code umwandelt.

    In diesem OperatingThread wird lediglich die TWatchdogs-Klasse instanziert und zur Laufzeit des Threads können (via Skript) Watchdogs erzeugt werden.

    Dass die Watchdogs erzeugt werden, kann ich überprüfen. Leider wird nach Auflauf des eingestellten Intervalls der zugewiese Handler NICHT ausgeführt, wenn der Timer "einfach so" innerhalb des Threads läuft.

    Interessanterweise ist es jedoch so, dass ich, wenn ich im Konstruktor den Timer auf fTimer->Enabled = true setze und direkt im Konstruktor ein fTimer->OnTimer aufrufe und im Hander z.B. ein ShowMessage() einbaue (der ja die weitere Abarbeitung des Konstruktors bis zum Wegklicken unterbricht), dann WIRD der zugewiesene Handler aufgerufen. Das ist daran erkennbar, dass nicht nur ein Message-Fenster erscheint, sondern im Interval-Zyklus des Timers weitere dazukommen.

    Sobald aber der Konstruktor abgearbeitet ist, wird wird das Event nicht mehr ausgelöst (die MessageBox wird nie wieder angezeigt).

    Bin ich zu blöd oder liegt an der der besonderen Situation, dass die Timer nicht im Hauptthread erzeugt werden.

    Hat jemand eine Idee?

    Danke im voraus

    Sören

  • #2
    TTimer benötigt eine funktinierende Windows Message Queue. AFAIK wirst du diese ohne gesonderte verrenkungen in einem Thread nicht haben. Ebenfalls ist der "normale" Timer nicht als Watchdog geeignet da du hier abhängig von Systemauslastung gewaltige Verzögerungen haben kannst.

    Ich würde einen Watch-Dog-Thread erzeugen und diesen für x ms schlafen legen. Beim Aufwachen löst dieser dann das Event aus.

    Comment


    • #3
      Hallo Bernhard,

      zunächst einmal ist es nicht allzu schlimm, wenn es zu Verzögerungen im Bereich bis zu 500 ms kommt, so genau kommt es bei diesen benutzer-definierten Watchdogs nicht darauf an, die liegen typischerweise eh im Bereich mehrerer Sekunden.

      Die Idee mit den eigenen WD-Treads erscheint mir auch sehr aufwändig: In meinem OperatingThread werden sie erzeugt, der HauptThread soll jedoch (zwecks Debugging) auch darauf zugreifen. Zudem legt man den Thread zwar mit Suspend(void) schlafen, aber um ihn zeitgesteuert wieder aufzuwecken, benötige ich ja auch wieder einen Zeitmesser (z.B. einen TTimer). Insofern sehe ich da auf den ersten Blick den Vorteil nicht.

      Wie kann man denn die Message Queue in einen Thread "umleiten", bzw. ihm diese zur Verfügung stellen?

      Sören

      Comment


      • #4
        http://msdn.microsoft.com/en-us/libr...90(VS.85).aspx

        http://msdn.microsoft.com/en-us/libr...43(VS.85).aspx
        Christian

        Comment

        Working...
        X