![]() |
Timer stoppen
Hallo
ich habe folgendes Problem: ich nutze eine Timer um zyklisch Werte aus einem Gerät zu holen (ja ich weiß, ein Thread wäre hier vielleicht angebrachter :-)) das klappt ja auch, mein Problem ist nun, das ich innerhalb meines Timers Application.ProcessMessages aufrufen muss, damit die Form weiter bedienbar bleibt. Jetzt will ich den Timer ja auch mal beenden:
Delphi-Quellcode:
Z.b.: wenn ich die Verbindung zur Schnittstelle beende.
meinTimer.enabled:=false;
Dann will ich auch mein Objekt freigeben:
Delphi-Quellcode:
MeinGeraet.Free;
Timerprozedur:
Delphi-Quellcode:
In meinem Disconnect Button mach ich folgendes:
procedure TMainGUI.tmrAblaufTimer(Sender: TObject);
begin MeinGeraet.HoleDies; Application.ProcessMessages; // angenommen mein Obj ist schon freigegeben (dann knallts) MeinGeraet.HoleJenes; Application.ProcessMessages; MeinGeraet.HoleDas; end;
Delphi-Quellcode:
Ich brauch hier eine Synchronisationsmethode, um auf das Ende vom der Timerprozedur zu warten, wie kann ich das machen???
begin
meinTimer.enabled:=false; // Timer soll beendet werden // Wie kann ich sicher gehen, dass der Timer nicht mehr aktiv ist, d.h. auch keine Timerprozedur mehr ausgeführt wird???? MeinGeraet.Free; end; Danke euch! end; |
Re: Timer stoppen
Vielleicht so?
Timerprozedur:
Delphi-Quellcode:
Timer soll beendet werden:
procedure TMainGUI.tmrAblaufTimer(Sender: TObject);
begin if MeinGereat <> nil then begin MeinGeraet.HoleDies; Application.ProcessMessages; MeinGeraet.HoleJenes; Application.ProcessMessages; MeinGeraet.HoleDas; end end;
Delphi-Quellcode:
begin
meinTimer.enabled:=false; // MeinGeraet.Free; FreeAndNil (MeinGeraet); end; |
Re: Timer stoppen
Du kannst aber eine global Variable, z.B.
Delphi-Quellcode:
und dann im Timer den an der Stelle den Status checken.
Enabled : Boolean
Oder ob der Timer.Enabled = True ist. Jedenfalls würde ich noch Bedingungen mit einbringen. |
Re: Timer stoppen
Zitat:
Alternativ eine Version ohne Application.ProcessMessages: Im Form deklarieren:
Delphi-Quellcode:
und dann
FtCount : Integer;
Delphi-Quellcode:
procedure TMainGUI.tmrAblaufTimer(Sender: TObject);
begin inc(FtCount); case FtCount of 1 : MeinGeraet.HoleDies; 2 : MeinGeraet.HoleJenes; 3 : begin MeinGeraet.HoleDas; FtCount := 0; end; end; end; |
Re: Timer stoppen
Kann ich denn über Sync-Objekte meine Timerprozedur so absichern,
dass diese Immer nur hintereinander ausgeführt wird?! Also erst die neue Timerproz ausführen, wenn die alte beendet ist? |
Re: Timer stoppen
Zitat:
hier ist ein Warten auf eine Antwort drin, das verögert meine GUI-Ausführung |
Re: Timer stoppen
was mir bei dem Quelltext auffällt:
Delphi-Quellcode:
wenn HoleDies, HoleJenes oder HoleDas etwas länger braucht wird bereits das nächste Timer-Event aufgerufen während bereits im Event etwas abgearbeitet wird.
procedure TMainGUI.tmrAblaufTimer(Sender: TObject);
begin MeinGeraet.HoleDies; Application.ProcessMessages; // angenommen mein Obj ist schon freigegeben (dann knallts) MeinGeraet.HoleJenes; Application.ProcessMessages; MeinGeraet.HoleDas; end; Daher lieber so:
Delphi-Quellcode:
procedure TMainGUI.tmrAblaufTimer(Sender: TObject);
begin TTimer(Sender).Enabled = False; MeinGeraet.HoleDies; Application.ProcessMessages; // angenommen mein Obj ist schon freigegeben (dann knallts) MeinGeraet.HoleJenes; Application.ProcessMessages; MeinGeraet.HoleDas; TTimer(Sender).Enabled = True; end; |
Re: Timer stoppen
Zitat:
EDIT: In Kombination mit SirThornberrys Vorschlag. (Das geht mir echt zu schnell hier - ich werde alt :| ) |
Re: Timer stoppen
@SirThornberry:
Ja stimmt, genau das könnte der Fall sein... aber bei deinem Quelltext, könnte es doch jetzt passieren, dass ich den Timer disable, und er noch die Prozedur abarbeitet, und dann sich selbst wieder aktiviert, oder?! Zitat:
Zitat:
|
Re: Timer stoppen
Das ist richtig. Du kannst ja am Ende das Enabled von einer Bedingung abhängig machen
Delphi-Quellcode:
TTimer(Sender).Enabled = Timer_still_needed;
|
Re: Timer stoppen
Zitat:
|
Re: Timer stoppen
genau, das Application ProcessMessages sorgt dort drin nur dafür das es möglich ist in einer anderen procedure das Object weg zu ziehen.
Daher am besten mit einem switch arbeiten und zusätzlich natürlich den Timer im Timer-Event abschalten falls eine Aktion mal etwas längert dauert damit sich die Timer-Events dann nicht aufstauen. |
Re: Timer stoppen
Zitat:
|
Re: Timer stoppen
Eher ersteres, Timer können sich "selbst überholen", wenn das Intervall im falschen Verhältnis zur benötigten Abarbeitungszeit steht.
|
Re: Timer stoppen
genau, sie stauhen sich in der Messagequeue. Das merkt man besonders gut wenn man mal einen Breakpoint setzt schritt für Schritt durchgeht und plötzlich wieder am Anfang der Funktion ist weil der nächste Aufruf durch Application.ProcessMessages kam.
|
Re: Timer stoppen
Zitat:
Ich glaube mich wieder erinnert zu haben: Wenn ein Timer sich "überholt" wird genau ein Event erzeugt, auch bei mehrfacher Überholung. Und das dann sofort ausgeführt, wenn der OnTimer abgearbeitet ist. Von daher ist SirThornberry's (Apostroph weil englisch) Idee gut, denn dann wird am Ende von OnTimer der Timer neu gestartet, und es vergeht ein Timerintervall bis zum nächsten Event. |
Re: Timer stoppen
Ich habe doch gar nichts Gegenteiliges behauptet. Wenn ich weiß, dass mein Timer evtl. länger als Intervall brauchen könnte, setze ich ihn auch immer auf false, lasse ihn abarbeiten und aktiviere ihn dann wieder.
|
Re: Timer stoppen
Zitat:
Das war mir noch gar nicht aufgefallen. Sollte man also besser nicht machen. |
Re: Timer stoppen
Zitat:
|
Re: Timer stoppen
Ja, ab 40 lässt die Reaktion rapide nach, ich kenne das :zwinker:
[edit] Rechtschreibung :oops: [/edit] |
Re: Timer stoppen
Zitat:
|
Re: Timer stoppen
[OT] Oh shit, ich bin als Zyniker entlarvt :mrgreen: [/OT]
|
Re: Timer stoppen
Zitat:
Löschen die Moderatoren den Unfug hier eigentlich wieder? Besser fänd ich das schon. Das is nix fürs Archiv :gruebel: [/OT] |
Re: Timer stoppen
gelöscht wirds nicht (auch sowas muss ab und zu sein sonst fehlt das persönliche und wir können uns gleich ein trockenes Lehrbuch nehmen) aber jetzt kommt ein dezenter Hinweis:
Lasst uns zum Thema zurück kommen :wink: |
Re: Timer stoppen
Hi,
ja stimmt, der Timer (so einfach er eigentlich ist) kann einem mit Application.ProcessMessages schlimme Probleme bereiten. Ich habe es jetzt so gelöst, dass er sich nicht selbst überholen kann:
Delphi-Quellcode:
TTimer(Sender).Enabled:=false;
.. .. .. .. .. TTimer(Sender).Enabled:=TimerSollLaufen; Wenn ich jetzt extern das Flag TimerSollLaufen auf False setze, dann wird der Timer nach Ablauf der OnTimer Prozedur beendet. Meine Frage ist nun, wie kann ich mir sicher sein, dass er wirklich beendet ist?! Ich habe den Timer.Tag dazu genutzt, mir anzuzeigen, ob er noch aktiv ist (1) oder beendet ist (0), doch wenn ich auf dieses Flag polle, dann bleibt der Timer einfach stehen! Gibt es dafür eine Erkärung?!
Delphi-Quellcode:
while tmrAblauf.Tag >0 do
begin Application.ProcessMessages; end; // Hier kommt er dann nie hin |
Re: Timer stoppen
*push* :roll:
|
Re: Timer stoppen
Wo setzt Du das Tag? Was machst Du sonst noch im Timer-Event? Wo steht die while-Schleife? Ohne den Kontext, in dem die Codeschnipsel stehen, kann ich mir keinen Kopp um Dein Problem machen. Mehr Code! Ich brauch mehr Code! :zwinker:
|
Re: Timer stoppen
Die vielen Application.ProcessMessages bringen den ganzen Message-Ablauf total durcheinander. In der selben Zeit, in der du versucht hast, dieses Problem zu richten, hättest du schon einen ganzen Thread samt Synchronisation schreiben können.
Zitat:
|
Re: Timer stoppen
Ok du willst Code du kriegst Code :-D
Delphi-Quellcode:
procedure TMainGUI.tmrAblaufTimer(Sender: TObject);
var active:Boolean; time1,time2:Cardinal; Failure:Boolean; begin TTimer(Sender).Enabled:=false; active:=False; if TimerIsActive then exit; try if not Assigned(aCS200) then Exit; TimerIsActive:=True; if TimeOut then exit; time1:=GetTickCount; tmrAblauf.Tag:= tmrAblauf.Tag+1; lblRequestVal.Caption:=IntToStr(tmrAblauf.Tag); Failure:=False; case tmrAblauf.Tag of 1 : begin if (aCS200.Get_TempIntern(TempIntern))=0 then begin pbFortschritt.Position:=7; end else begin Failure:=True; end; end; 2 : begin if (aCS200.Get_TempExtern(TempExtern))=0 then begin pbFortschritt.Position:=14; end else begin Failure:=True; end; end; 3 : begin if (aCS200.Get_StoerungsFlags(stoerungsflags))=0 then begin pbFortschritt.Position:=21; end else begin Failure:=True; end; end; 4 : begin if (aCS200.Get_SollWertFanIntern(SollWertFanIntern))=0 then begin pbFortschritt.Position:=28; end else begin Failure:=True; end; end; 5 : begin if (aCS200.Get_FanInternSpeed_1(fan1InternSpeed))=0 then begin pbFortschritt.Position:=35; end else begin Failure:=True; end; end; 6 : begin if (aCS200.Get_Fan1InternPuls(fan1InternPuls))=0 then begin pbFortschritt.Position:=42; end else begin Failure:=True; end; end; 7 : begin if (aCS200.Get_FanInternSpeed_2(fan2InternSpeed))=0 then begin pbFortschritt.Position:=49; end else begin Failure:=True; end; end; 8 : begin if (aCS200.Get_Fan2InternPuls(fan2InternPuls))=0 then begin pbFortschritt.Position:=56; end else begin Failure:=True; end; end; 9 : begin if (aCS200.Get_SollWertFanExtern(SollWertFanExtern))=0 then begin pbFortschritt.Position:=63; end else begin Failure:=True; end; end; 10: begin if (aCS200.Get_FanExternSpeed_1(fan1ExternSpeed))=0 then begin pbFortschritt.Position:=70; end else begin Failure:=True; end; end; 11: begin if (aCS200.Get_FanExternSpeed_2(fan2ExternSpeed))=0 then begin pbFortschritt.Position:=77; end else begin Failure:=True; end; end; 12: begin if (aCS200.Get_Fan1ExternPuls(fan1ExternPuls))=0 then begin pbFortschritt.Position:=84; end else begin Failure:=True; end; end; 13: begin if (aCS200.Get_Fan2ExternPuls(fan2ExternPuls))=0 then begin pbFortschritt.Position:=91; end else begin Failure:=True; end; end; 14: begin if (aCS200.Get_StoerungsFlags(stoerungsflags))=0 then begin pbFortschritt.Position:=95; end else begin Failure:=True; end; end; 15: begin if (aCS200.Get_IOFlags(IOflags))=0 then begin pbFortschritt.Position:=98; end else begin Failure:=True; end; end; 16: begin if (aCS200.Get_StatusFlags(Statusflags))=0 then begin pbFortschritt.Position:=100; end else begin Failure:=True; end; end; 100 +1: begin WriteDataToDevice(Self); end; 200 +1: begin ReadDataFromDevice(Self); end else begin tmrAblauf.Tag := 0; pbFortschritt.Position:=0; end; end; if Failure then begin MessageDlg('Fehler beim Lesen der Daten aus dem Wärmetauscher',mtError,[mbOK],0); exit; end; if TimeOut then begin exit; end; if Assigned(aCS200) then begin if aCS200.FSCI.isConnected then begin if not( (Assigned( aCS200 ))) then Exit; lnAkuelleInnenTemp.Clear; lnAktuelleAussenTemp.Clear; if not(stoerungsflags[8]) then begin // zeichne Aktuelle Innentemp auf Graph "Innenkreis" lnAkuelleInnenTemp.AddXY(TempIntern,-20,'',clBlack); lnAkuelleInnenTemp.AddXY(TempIntern+0.1,120,'',clBlack); // zeichne Aktuelle Innentemp auf Graph "Aussenkreis" lnAktuelleAussenTemp.AddXY(TempIntern,-20,'',clBlack); lnAktuelleAussenTemp.AddXY(TempIntern+0.1,120,'',clBlack); end else begin TempIntern:=-40; end; lblTempInternVal.Caption:=IntToStr(TempIntern) + ' [°C]'; if (Statusflags[7]) then begin // TempFühler Aussen ist wirklich vorhanden lblTempExternVal.Caption:=IntToStr(TempExtern) + ' [°C]'; end else begin lblTempExternVal.Caption:=' --' + ' [°C]'; end; lblSollWertFanInternVal.Caption:=IntToStr(SollWertFanIntern) + ' [%] '; lblFanSpeed1InternVal.Caption:=IntToStr(fan1InternSpeed)+ ' [rpm] ' + ' bei '+IntToStr(fan1InternPuls)+ ' [P/s]'; lblFanSpeed2InternVal.Caption:=IntToStr(fan2InternSpeed)+ ' [rpm]'+ ' bei '+IntToStr(fan2InternPuls)+ ' [P/s]'; lblSollWertFanExternVal.Caption:=IntToStr(SollWertFanExtern) + ' [%] '; lblFanSpeed1ExternVal.Caption:=IntToStr(fan1ExternSpeed)+ ' [rpm] ' + ' bei '+IntToStr(fan1ExternPuls)+ ' [P/s]'; lblFanSpeed2ExternVal.Caption:=IntToStr(fan2ExternSpeed)+ ' [rpm]'+ ' bei '+IntToStr(fan2ExternPuls)+ ' [P/s]'; if IOflags[6] then begin ledTuerkontakt.ColorOn:=clLime; end else begin ledTuerkontakt.ColorOn:=clGray; end; if IOflags[5] then begin ledEndSchalter1.ColorOn:=clLime; end else begin ledEndSchalter1.ColorOn:=clGray; end; if IOflags[4] then begin ledEndSchalter2.ColorOn:=clLime; end else begin ledEndSchalter2.ColorOn:=clGray; end; if IOflags[3] then begin ledInAlarm1.ColorOn:=clLime; end else begin ledInAlarm1.ColorOn:=clGray; end; if IOflags[2] then begin ledInAlarm2.ColorOn:=clLime; end else begin ledInAlarm2.ColorOn:=clGray; end; if IOflags[8] then begin ledAlarm1.ColorOn:=clRed; end else begin ledAlarm1.ColorOn:=clGray; end; if IOflags[9] then begin ledAlarm2.ColorOn:=clRed; end else begin ledAlarm2.ColorOn:=clGray; end; if IOflags[10] then begin ledAlarm3.ColorOn:=clRed; end else begin ledAlarm3.ColorOn:=clGray; end; if IOflags[11] then begin ledHeizung.ColorOn:=clLime; end else begin ledHeizung.ColorOn:=clGray; end; if IOflags[12] then begin ledSammelstoerung.ColorOn:=clLime; end else begin ledSammelstoerung.ColorOn:=clGray; end; if IOflags[13] then begin ledExtern.ColorOn:=clLime; end else begin ledExtern.ColorOn:=clGray; end; if IOflags[14] then begin ledIntern.ColorOn:=clLime; end else begin ledIntern.ColorOn:=clGray; end; // Stoerungsflags lstStoerung.Clear; if stoerungsflags[8] then begin lstStoerung.AddItem('Temp-Sensor (intern) def.',nil); lblTempInternVal.Caption:='-- ' + ' [°C]'; TempIntern:=-40; end; if stoerungsflags[7] then begin lstStoerung.AddItem('Temp-Sensor (extern) def.',nil); lblTempExternVal.Caption:='-- ' + ' [°C]'; end; if stoerungsflags[6] then begin lstStoerung.AddItem('Feuchte-Sensor def.',nil); end; if stoerungsflags[1] then begin lstStoerung.AddItem('Fan-2 (extern) def.',nil); end; if stoerungsflags[2] then begin lstStoerung.AddItem('Fan-1 (extern) def.',nil); end; if stoerungsflags[3] then begin lstStoerung.AddItem('Fan-2 (intern) def.',nil); end; if stoerungsflags[4] then begin lstStoerung.AddItem('Fan-1 (intern) def.',nil); end; if stoerungsflags[5] then begin lstStoerung.AddItem('Heizung def.',nil); end; active:=True; end else begin InitGUI; exit; end; end; time2:=GetTickCount -time1; finally // windows.Beep(1500,200); TTimer(Sender).Enabled:=TimerSollLaufen; if not(TimerSollLaufen) then InitGUI; TimerIsActive:=false; if active then begin ledVerbunden.ColorOn:=clLime;; end else begin ledVerbunden.ColorOn:=clGray; end; end; end; |
Re: Timer stoppen
Nach dem ersten Timer-Event ist tmrAblauf.Tag immer größer Null, richtig?
Und mit den Exit springst du am finally Block vorbei raus. Ist das Absicht? |
Re: Timer stoppen
Zitat:
|
Re: Timer stoppen
Ja ist schon richtig, und so gewollt.
Deswegen stehts ja nicht im try Block. |
Re: Timer stoppen
Zitat:
|
Re: Timer stoppen
Eine Frage, etwas OT, habe ich zur Codeformatierung:
Delphi-Quellcode:
Gilt das heutzutage als schlechter Stil, und ich werde gesteinigt, weil ich "Jehova" gesagt habe? Ich finde das wesentlich übersichtlicher, weil man weniger scrollen muss.
if (aCS200.Get_TempIntern(TempIntern))=0 then
begin pbFortschritt.Position:=7; end else begin Failure:=True; end; // so würde ich das schreiben: if (aCS200.Get_TempIntern(TempIntern)) = 0 then pbFortschritt.Position := 7 else Failure := True; |
Re: Timer stoppen
Die Lösung war doch schon fast gefunden, ich mache es mit den Timern immer so:
procedure Tmainform.Timer1Timer(Sender: TObject);
Delphi-Quellcode:
Damit kann man Mehtfachaufruf sicher verhindern.
begin
try if timer1.Tag>0 then exit; timer1.Tag:=1; Tu Was .... finally timer1.Tag:=0; end; Gruß |
Re: Timer stoppen
Meine ursprüngliche Frage war eigentlich,
wie ich feststelle, dass die Timerprozedur fertig abgearbeitet ist, angenommen ich nutzt dort ein Objekt, das ich woanders freigeben will, dann muss ich dort warten bis die Prozedur beendet ist. |
Re: Timer stoppen
Zitat:
|
Re: Timer stoppen
Hi,
nee veräppeln will ich hier niemanden, aber vielleicht steh ich ja auch gerade aufm Schlauch :? Ich habe ja 1 Flag -TimerIsActive Das setze ich beim Entritt und lösche es beim Austritt der Prozedur. Wenn ich jetzt auf dieses Flag polle bis es False ist dann habe ich einen Deadlock... |
Re: Timer stoppen
Zitat:
Das ist in der Tat seltsam. Ich würde herumexperimentieren, um diesem Problem auf die Schliche zu kommen. Wenn Du den Timer sehr langsam einstellst (sagen wir mal so 3s, pi mal daumen) - taucht dann das Phänomen noch auf? |
Re: Timer stoppen
Hi bluesbear,
das werde ich mal probieren, versuche das mal über extreme Debugging :lol: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz