Einzelnen Beitrag anzeigen

Rupert

Registriert seit: 10. Nov 2013
23 Beiträge
 
#45

AW: Nach Timer.Enable killt sich das Programm

  Alt 11. Okt 2021, 17:16
Ursache gefunden - Problem gelöst.

Das Programm hat nicht nur den Timer, der die Hauptschleife triggert, sondern es gibt noch zwei weitere.
Ein Timer (Timer-A) dient dazu, dass der Heizkessel seinen Impuls bekommt, sich einzuschalten und der andere Timer (Timer-B) erfüllt den Zweck, dass ein oder mehrere Räume schnell aufgeheizt werden (Ferienwohnung wurde kurzfristig gebucht und muss auf Normaltemperatur gebracht werden).

Timer-A läuft 25 min (Kessel)
Timer-B läuft 4 Stunden (Raumheizung)

Timer-B wird durch den Button extra heizen ausgelöst oder auch gestoppt:
Delphi-Quellcode:
  if extraheizenchecked then begin
    if Timer_Extra_heizen.Enabled then begin
      Timer_Extra_heizen.visible:=true;
      Timer_Extra_heizen.StartCountdown;
    end;
  end else
    Timer_Extra_heizen.EndCountdown;
Ereignis OnCountdownEnd sieht so aus:
Delphi-Quellcode:
procedure THauptformular.Timer_Extra_heizenCountdownEnd(Sender: TObject);

var i:SmallInt;

begin
    extraheizenchecked:=false;

    for i:=1 to 23 do // alle Räume
      if Extra_heizen[i] then begin
        Extra_heizen[i]:=false; // Status löschen
        Heizstatus[i]:= normal_erreicht; //egal bei welcher tats. Temperatur
    end;
    Timer_Extra_heizen.Enabled:=false;
    Timer_Extra_heizen.visible:=false;
end;
Dieser Timer verursachte das Problem nicht. Aber Timer-A, der so ähnlich aussieht.

Timer-A:
Der Pellets Heizkessel muss mindestens 25 min laufen, damit der Kamin nicht versottet.

Ereignis OnCountdownEnd sah so aus:

Delphi-Quellcode:
procedure THauptformular.Kessel_Ende_Countdown(Owner:TObject);

Begin
  Kessel_manuell_ein:=false;
  Kesseluhr.Endcountdown();
  Kesseluhr.Visible:=false;
  // kessel wird erst abgeschaltet, wenn die Vorlauf-Temperaturbedingungen erfüllt sind
  Abfrage_Kessel_Ausschalten(nil);
end;
Jeder Timer bedient sich des Windows API Timers und deshalb sah es so aus, als würde der Hauptschleifentimer den Crash verursachen. Tatsächlich verursachte jedoch Timer-A den Stack-Overflow. Nachdem ich mich nicht auf diesen Timer konzentriert habe, fand ic auch die Ursache für den Stack-Overlow nicht sofort.
Erst, als ich einen Demomode eingebaut hatte, um das Programm außerhalb des Heizcomputers zu betreiben erhielt ich die Position, wo sich das Programm gekillt hat - bei der Procedure Kessel_Ende_Countdown
Delphi-Quellcode:
Begin
  Kessel_manuell_ein:=false;
  Kesseluhr.Endcountdown(); // hier wurde Kessel_Ende_Countdown rekursiv aufgerufen
  Kesseluhr.Visible:=false;
  // kessel wird erst abgeschaltet, wenn die Vorlauf-Temperaturbedingungen erfüllt sind
  Abfrage_Kessel_Ausschalten(nil);
end;
Warum der Stack-Overflow nicht bei jedem Kessel_Ende_Countdown ausgelöst wurde weiß ich nicht, ist mir aber nun egal. Die Zeile muss irgendwann versehentlich durch copy/paste hineingerutscht sein, da ich in der Doku keinen Hinweis auf Änderung der Procedure fand.

Vielen, vielen Dank an euch alle.
Ihr habt mich großartig unterstützt, denn durch eure Hinweise kam ich dem Verursacher immer näher und fand schließlich die kurze, aber todbringende Zeile, was bei 8032 Programmzeilen gar nicht mehr so einfach ist!
  Mit Zitat antworten Zitat