Autor Beitrag
gispos
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 94

WIN 7
XE10, D2007
BeitragVerfasst: Mo 24.11.08 20:12 
Hallo zusammen,
ich habe da ein Problem mit Befehlen die aus einem Loop heraus ausgeführt werden.

Unterer Code ist nur ein kleines Beispiel, dass so aber in meinem richtigen Code auftreten kann. Es wird aus dem Loop heraus in eine andere Procedure gesprungen hier (Check), dort wird ein Wert geprüft und bei Erfolg sofort der Loop mit nächstem Index weiter ausgeführt, was dann aber bei ca. 100000 Durchläufen zu einem Stack Überlauf führt.

Einzige Möglichkeit um dies zu vermeiden ist das RunLoop über PostMessage zu senden (Check_Post), was aber den Nachteil des langsamen ausführen mit sich bringt und dadurch falsche Ergebnisse liefern kann.

Entweder sehe ich vor lauter Bäumen den Wald nicht, oder… meine Kenntnisse reichen nicht aus. :(
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
const
  WM_RUNLOOP = WM_USER + 99;

// Hier wird das Application.OnMessage verarbeitet
procedure TForm1.OnAppMessage(var Msg : tagMSG; var Handled : Boolean);
begin
  If Msg.message = WM_RUNLOOP then
  begin
    Handled:= True;
    RunLoop(Msg.WParam);
  end
  else Handled := False;
end;

// Kein Stack Überlauf, aber langsam
procedure Check_Post;
begin
  PostMessage(Application.Handle, WM_RUNLOOP, CurrLoop + 10);
end;

// Stack Überlauf
procedure Check;
begin
  {Normal wird hier ein Wert geprüft, wenn True wird z.B. ein Thread gestartet
   Wenn False, sofort RunLoop, und dann gibt’s aber Probleme
  If not Wert then WaitThread := TWaitThread.Create(Wert);
  else}

    Form1.RunLoop(CurrLoop + 1);
end;

// Enthält normal ca. 70 Aktionen die Proceduren mit Wert Übergabe aufrufen.
// Je nach Ergebnis muss der Loop dann beendet und später durch die Prüfende Procedure
// wieder gestartet werden.
procedure TForm1.RunLoop(Index: Integer);
begin
  While Index < 100000 do
  begin
    CurrLoop := Index;
    inc(Index);
    Application.ProcessMessages;

    // Stack Überlauf
    Check;

    // Kein Stack Überlauf
    {Check_Post;}

    exit; 
  end;
end;

// Beispiel des Starts 
procedure TForm1.Button1Click(Sender: TObject);
begin
  Application.OnMessage := OnAppMessage;
  Caption := 'Start';
  RunLoop(0);
  Caption := 'Fin';
end;


Vielleicht sollte ich alle Proceduren in die Procedure RunLoop mit einbinden, so das bei Erfolg nicht in den Loop gesprungen wird. Sind aber ca. 50 Proceduren und da müsste ich dann einiges Umschreiben.

Kann mir da jemand weiterhelfen?
Gruß gispos
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mo 24.11.08 20:49 
Klingt für mich nach endloser doppelter Rekursion: Prozedur A ruft B auf, die ruft A auf, die ruft B auf, die ruft A auf ... und in null komma nix ist der Aufrufestack voll. Du musst bedenken, wenn A B aufgerufen hat, ist A immernoch auf dem Stack. dann ruft B A auf, und dann sieht der stack so aus: A-B-A. und es geht weiter, denn A ruft ja wieder B auf: A-B-A-B-A-B... Das ist etwas, auf das man bei Rekursion achten muss.

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
gispos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 94

WIN 7
XE10, D2007
BeitragVerfasst: Mo 24.11.08 21:21 
JayEff mal danke für deine Antwort… hilft mir nur leider nicht weiter.

Ja der Stack häuft die einzelnen Aufrufe an und ist irgendwann voll weil die Schleife noch nicht beendet war und wieder in die Schleife gesprungen wird.

Wie kann ich dies aber am besten vermeiden ohne mein RunLoop zum Stillstand zu bringen?

Hat sich erledigt. :D
Muss eben alle Proceduren in Functionen umschreiben.
Wenn True zurück geliefert wird läuft die Schleife einfach weiter.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
// Es wird nicht mehr in die Schleife gesprungen
Function Check : boolean;
Begin
  If Wert then Result := True
  else begin
    Result := False;
    WaitThread := TWaitThread.Create(Wert);
  end;
End;

Procedure RunLoop(Index : Integer);
Begin
  While Index < 100000 do
  Begin
    CurrLoop := Index;
    Inc(Index);
    Application.ProzessMessages;
    If not Check then exit; // ansonsten wird das Loop weiter ausgeführt
  End;


Gruß gispos