For-Schleife mit Ausgabe wie Diashow

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von theo »

Zu lange sollte man sicher nicht blocken, aber 150ms sind - soweit mir bekannt ist- kein Problem und deshalb sollte man auch keines draus machen.
Wenn jemand etwas belastbares hat was dagegen spricht, dann soll er es bitte zeigen.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von mschnell »

theo hat geschrieben:Warum darf ein Main-Thread nicht 150 ms sleepen? Wo steht das? Was passiert dann?
Wie Du sicher weißt bleibt dann für die Wartezeit die Event-Queue stehen und nichts passiert in diesem Programm. Keine Ausgaben auf dem Bildschirm, keine Reaktion auf Timer, Tasten-, Maus-, Serien-Schnittstellen- oder Netzwerk-Input, Windows-Messages, Pipes, ... . Die ganze Infrastruktur der LCL wird eingefroren, und man sollte sich nicht unbesehen darauf verlassen, dass die LCL das klaglos mitmacht.

Da kann man - je nach Applikation - für 150 mS möglicherweise mit leben, wenn man genau weiß was man tut. Um potentielle verborgene Probleme zu vermeiden sollte man aber auf sauberes Event-Orientiertes Programmieren des Mainthreads achten.

-Michael

Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von theo »

mschnell hat geschrieben: Wie Du sicher weißt bleibt dann für die Wartezeit die Event-Queue stehen und nichts passiert in diesem Programm. Keine Ausgaben auf dem Bildschirm, keine Reaktion auf Timer, Tasten-, Maus-, Serien-Schnittstellen- oder Netzwerk-Input, Windows-Messages, Pipes, ... . Die ganze Infrastruktur der LCL wird eingefroren, und man sollte sich nicht unbesehen darauf verlassen, dass die LCL das klaglos mitmacht.
Das muss das System mMn mitmachen, sonst könnte man auch keine blockierenden Internet Sachen wie z.B. Synapses HttpGetText im Mainthread machen.
Das ist übrigens mMn problematischer als ein sleep.
mschnell hat geschrieben: Da kann man - je nach Applikation - für 150 mS möglicherweise mit leben, wenn man genau weiß was man tut.
Hier geht es um eine Diashow. Ich sehe kein Problem, wenn jew. nach 150ms ProcessMessages aufgerufen wird.

InfoSchülerktog
Beiträge: 9
Registriert: Fr 6. Mär 2015, 09:07

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von InfoSchülerktog »

Mein Code ist ewig lang und es wäre sehr umständlich das programm zu erklären, da es eben kein standard spiel oder sowas ist.
Was das mit dem sleep angeht so läuft das bei mir problemlos, egal wo ich es bisher getestet habe.
Ich habe halt erfahren dass dieser SIGSEGV error meistens etwas mit den compiler einstellungen zu tun hat, nur habe ich keine Ahnung was man da genau einstellen könnte...

Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von theo »

InfoSchülerktog hat geschrieben: Ich habe halt erfahren dass dieser SIGSEGV error meistens etwas mit den compiler einstellungen zu tun hat, nur habe ich keine Ahnung was man da genau einstellen könnte...
Wo "erfährt" man denn sowas?
Mit grösster Wahrscheinlichkeit greift dein Programm auf einen Speicherbereich zu, den es nicht reserviert hat.
Z.B. so:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var s:TStringList;
begin
  s.text:='test'; //geht in die Hose, weil s nicht created wurde.
end; 
Das kriegt man mit keiner FPC Compilereinstellung weg, sondern mit sauberem programmieren.

Warf
Beiträge: 2120
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von Warf »

InfoSchülerktog hat geschrieben:Mein Code ist ewig lang und es wäre sehr umständlich das programm zu erklären, da es eben kein standard spiel oder sowas ist.
Was das mit dem sleep angeht so läuft das bei mir problemlos, egal wo ich es bisher getestet habe.
Ich habe halt erfahren dass dieser SIGSEGV error meistens etwas mit den compiler einstellungen zu tun hat, nur habe ich keine Ahnung was man da genau einstellen könnte...
Überprüfe mal ob der Timer richtig erstellt wurde, wenn nicht lösche ihn einfach aus der Form und erstell einen neuen.
Sleep hat ein Riesen Problem, es hält dein gesamtes Programm auf, eine eingefrorene Form ist das letzte was du haben möchtest. Eine Lösung wäre in regelmäßigen Abständen während dem Warten Application.ProcessMesages; aufzurufen, dann musst du aber auch dafür sorgen, dass bei bestimmten Events du deine Prozedur anpasst, z.B. wenn die Form geschlossen werden soll, dass du dann die Prozedur vorzeitig verlässt, etc. Und grade wenn du eine Aufwändige GUI hast kann es sein, dass dies sehr aufwendig werden kann.

Bei einem Timer läuft das ganze Event Basiert, und wenn du es Abbrechen willst stellst du einfach vom Timer die Eigenschaft Enabled auf False. Wichtig ist nur, dass du während dem Lauf des TimerEvents den Timer Deaktivierst, sonst, wenn die Methode innerhalb des Timers zu lange braucht, kann es sein dass diese erneut aufgerufen wird, bevor die erste zu Ende ist (Was unschön werden kann)

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von mschnell »

theo hat geschrieben: Das muss das System mMn mitmachen, sonst könnte man auch keine blockierenden Internet Sachen wie z.B. Synapses HttpGetText im Mainthread machen. Das ist übrigens mMn problematischer als ein sleep.
Das ist natürlich wirklich problematischer. Der TCP/IP Timeout kann Minuten lang sein. Da würde ich nicht wollen, dass die GUI des Programms eingefroren bleibt.

-Michael

InfoSchülerktog
Beiträge: 9
Registriert: Fr 6. Mär 2015, 09:07

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von InfoSchülerktog »

Der Timer läuft einwandfrei, habe ihn einfach mal die werte in ein Edit schreiben lassen und da gesehen, dass es funktioniert.
Das mit dem sleep werde ich dann wohl besser doch umgehen, danke für den tipp :)

InfoSchülerktog
Beiträge: 9
Registriert: Fr 6. Mär 2015, 09:07

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von InfoSchülerktog »

Compilieren lässt sich alles, sobald ich den Timer über den Button starten will kommt in der gekennzeichneten Zeile die Fehlermeldung "Hat Exception-Klasse >>External: SIGSEGV<< ausgelöst.
Kann mir vllt irgendjmd sagen, woran das liegen könnte?
Zuletzt geändert von InfoSchülerktog am Di 17. Mär 2015, 17:12, insgesamt 2-mal geändert.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6780
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von af0815 »

InfoSchülerktog hat geschrieben:Ich habe halt erfahren dass dieser SIGSEGV error meistens etwas mit den compiler einstellungen zu tun hat, nur habe ich keine Ahnung was man da genau einstellen könnte...
Wenn man keine Ahnung hat, so kann man auch die Hilfe verwenden, ist ausdrücklich NICHT VERBOTEN.

Es sind ziemlich sicher in den Projektoptionen die Einstellungen zum Debugging gemeint. Damit werden die meisten Fehler schon beim kompilieren angezeigt.

Unter Projekt -> Projektoptionen den Dialog aufmachen und dort bei Debugging die Häckchen setzen.

PS: Wollte hier ein Bild (egal ob PNG,JPG und GIF) hochladen, bekomme aber immer die Meldung von der Forumssoftware: Die Größe des Bildes konnte nicht ermittelt werden
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von mschnell »

af0815 hat geschrieben:Wenn man keine Ahnung hat, so kann man auch die Hilfe verwenden, ist ausdrücklich NICHT VERBOTEN.
Nicht so verärgert schreiben :?

Wenn ein Lazarus-Einsteiger anscheinend noch nicht erklärt bekommen hat, was Ereignis-orientierte Programmierung bedeutet, dann ist auch nicht zu erwarten, dass er mit der - leider gegenüber Delphi stark defizitären - Hilfe noch nicht klarkommt.

Lazarus ist - bei allen unverkennbaren Vorteilen - leider wirklich nicht Einsteiger-freundlich.

-Michael
Zuletzt geändert von mschnell am Fr 13. Mär 2015, 09:17, insgesamt 1-mal geändert.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6780
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von af0815 »

mschnell hat geschrieben:Wenn ein Lazarus-Einsteiger anscheinend noch nicht erklärt bekommen hat, was Ereignis-orientierte Programmierung bedeutet, dann ist auch nicht zu erwarten, dass er mit der - leider gegenüber Delphi stark defizitären - Hilfe noch nicht klarkommt.
Der Satz deutet eher darauf hin, das man sich nicht mit Dokumentation auseinandersetzen will. Es gibt in den Dialogen immer öfter den Button Hilfe, wenn der Benutzt wird, so kommt man derzeit auf die Wiki. Dort ist auch immer öfter das ganze auf Deutsch erklärt. Zumindest sieht dann die Frage bzw. die Aussage ganz anders aus.

Eine kurze Übersicht der Dokus, wo sie sind und was sie als Basis haben isthier unter Lazarus Docszu finden.

Nebenbei macht ja auch der Sytaxhighlighter hier im Forum ein massives Problem. Der ist so gut versteckt das ihn keiner der Newbees findet.

BTW: Der Code ist ja nicht mal vollständig was gepostet wurde, das fehlt das halbe Interface.

Hier ist das auch alles anderes als klar ?!

Code: Alles auswählen

procedure TForm9.Timer1Timer(Sender: TObject);
begin
Inc(Zaehler2);
if Zaehler2 = 24 then begin
WuerfelGridTimer.Enabled := False;
end;
 
{procedure TForm9.WuerfelButtonClick(Sender: TObject);
begin }
For zaehler2:=1 To 24 Do
begin
{WuerfelGridTimer.Enabled:=False; }
randomize; sleep(115);
randomize;
Das ist unlesbar.

Das folgende ist lesbarer, nur ich werde nicht den ganzen Kode nachbauen, lesbarer gestalten um dann zu sehen wo das Problem ist. Und man sieht auch schöner, das zB. der Zaehler2 nicht richtig verwendet wird. Entweder in als Zähler ODER als FOR VARIABLE aber bitte nicht alles zugleich.

Code: Alles auswählen

procedure TForm9.Timer1Timer(Sender: TObject);
begin
  Inc(Zaehler2);
  if Zaehler2 = 24 then begin
    WuerfelGridTimer.Enabled := False;
  end;
 
  For zaehler2:=1 To 24 Do
  begin
    randomize; 
    sleep(115);
    randomize;
Meistens ist das Problem sichtbarer, wenn auch der Code lesbarer ist. Alte Erfahrung aus ca. 30 Jahren Programmierung.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

InfoSchülerktog
Beiträge: 9
Registriert: Fr 6. Mär 2015, 09:07

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von InfoSchülerktog »

bisher habe ich die fehler auch alle beheben können, nur bei einem SIGSEGV weiß ich nicht weiter.
Zuletzt geändert von InfoSchülerktog am Di 17. Mär 2015, 17:15, insgesamt 1-mal geändert.

Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von theo »

InfoSchülerktog hat geschrieben: ganz einfach, weil es in der kompilierung keinen fehler gibt! sowohl variablen als auch uses sind vollständig und korrekt und ich wollte den code nicht noch länger machen als er ohnehin schon ist...
SIGSEGV gibt nie bei der Kompilierung Fehler, sonst gäbe es ihn ja gar nicht. :roll:
InfoSchülerktog hat geschrieben: bisher habe ich die fehler auch alle beheben können, nur bei einem SIGSEGV weiß ich nicht weiter, da wir sowas nie im unterricht behandelt haben und auch im internet wenig zu diesem fehler zu finden ist. mit kompilereinstellungen haben wir uns eben nie auseinandergesetzt
Wie schon geschrieben, hat SIGSEGV mit Kompilereinstellungen nichts zu tun.

Um den Fehler zu finden, muss man den ganzen Code sehen.

Warf
Beiträge: 2120
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: For-Schleife mit Ausgabe wie Diashow

Beitrag von Warf »

Ich habe den Code mal Formatiert und dir angestrichen was ich irgendwie befremdlich finde, ein sauberer Code ist der wichtigste Schritt zur Fehler Behebung (glaub mir)

Code: Alles auswählen

var
  Form9: TForm9;
  zaehler, wuerfel1, wuerfel2, Ergebnis, Anzahl, spalte, zeile,
  SpalteEdit, ZeileEdit, zaehler2: integer;  //xxxEdit ist ungünstige namenswahl
  Takt: string;
  WuerfelGrid: TStringGrid;  //warum als globale variable?
 
 
implementation
 
 
    {$R *.lfm}
 
{ TWuerfelForm }
procedure TForm9.Timer1Timer(Sender: TObject);
begin
  Inc(Zaehler2);          //Das soll die For-Schleife ersetzen
  if Zaehler2 = 24 then
  begin
    WuerfelGridTimer.Enabled := False;
  end;
 
  for zaehler2 := 1 to 24 do
  begin
    randomize;    //Randomize einmal beim Start des programmes ausführen reicht völlig aus
    sleep(115);
    randomize;
 
    wuerfel1 := Random(6) + 1;
 
    case wuerfel1 of          //Lässt sich einzeilig lösen, besser wäre als array
      1: Wuerfel1Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel1.png');
      2: Wuerfel1Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel2.png');
      3: Wuerfel1Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel3.png');
      4: Wuerfel1Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel4.png');
      5: Wuerfel1Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel5.png');
      6: Wuerfel1Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel6.png');
 
    end;
 
    wuerfel2 := Random(6) + 1;
 
    case wuerfel2 of         //s.O.
 
      1: Wuerfel2Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel1.png');
      2: Wuerfel2Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel2.png');
      3: Wuerfel2Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel3.png');
      4: Wuerfel2Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel4.png');
      5: Wuerfel2Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel5.png');
      6: Wuerfel2Image.Picture.LoadFromFile('\Endprojekt\bilder\würfel6.png');
 
    end;
 
    Ergebnis := wuerfel1 + wuerfel2;
    Augenzahledit.Text := IntToStr(Ergebnis);
 
    Anzahl := Anzahl + 1;
    Anzahledit.Text := IntToStr(Anzahl);
 
 
 
    //Tabelle füllen
 
    WuerfelGrid.cells[spalte, zeile] := IntToStr(Ergebnis);
    zaehler := zaehler + 1;
 
    //Ließe sich alles arithmetisch lösen mit Spalte := zaehler div 8; Zeile := Zaehler mod 8
    //kürzer in form eines Case ... of
    if zaehler = 9 then
    begin
      spalte := 1;
      zeile := 0;
    end;
 
    if zaehler = 17 then
    begin
      spalte := 2;
      zeile := 0;
    end;
    zeile := zeile + 1;
 
    if zaehler = 25 then
      WuerfelButton.Enabled := False;
 
    //Arithmetisch: Spaltenedit := Anzahl mod 8
    //alle 3 if blöcke unterscheiden sich in nur einer Zeile, der rest kann alleine drunter stehen
    if Anzahl < 9 then
    begin
      SpalteEdit := Anzahl;
      ZeileEdit := Ergebnis - 1;
      Takt := (stringgrid1.cells[SpalteEdit, ZeileEdit]);
      edit1.Text := Takt;
      edit2.Text := IntToStr(ZeileEdit);
      edit3.Text := IntToStr(SpalteEdit);
 
    end;
 
    if (Anzahl > 8) and (Anzahl < 17) then
    begin
      SpalteEdit := Anzahl - 8;
      ZeileEdit := Ergebnis - 1;
      Takt := (stringgrid1.Cells[SpalteEdit, ZeileEdit]);
      edit1.Text := Takt;
      edit2.Text := IntToStr(ZeileEdit);
      edit3.Text := IntToStr(SpalteEdit);
 
    end;
 
    if Anzahl > 16 then
    begin
      SpalteEdit := Anzahl - 16;
      ZeileEdit := Ergebnis - 1;
      Takt := (stringgrid2.Cells[SpalteEdit, ZeileEdit]);
      edit1.Text := Takt;
      edit2.Text := IntToStr(ZeileEdit);
      edit3.Text := IntToStr(SpalteEdit);
 
    end;
    begin   //begin?
      case Anzahl of   //ein array würde es wohl besser tun
        1: Image1.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte' + Takt + '.jpg');
        2: Image2.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        3: Image3.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        4: Image4.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        5: Image5.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        6: Image6.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        7: Image7.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        8: Image8.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        9: Image9.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        10: Image10.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        11: Image11.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        12: Image12.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        13: Image13.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        14: Image14.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        15: Image15.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        16: Image16.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\1005.jpg');
        17: Image17.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        18: Image18.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        19: Image19.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        20: Image20.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        21: Image21.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        22: Image22.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        23: Image23.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
        24: Image24.Picture.LoadFromFile('\Endprojekt\KV_294d\Takte\' + Takt + '.jpg');
      end;
    end;
  end;
end;
 
procedure TForm9.Button1Click(Sender: TObject);
begin
  Close;
end;
 
procedure TForm9.Button2Click(Sender: TObject);
begin
  WuerfelGridTimer.Enabled := True;
  Zaehler := 0;
end;
 
//Form Create Event ist besser
begin
  zaehler := 1;
  spalte := 0;
  zeile := 1;
  Anzahl := 0;
end.     
generell habe ich das Gefühl, du hast das mit dem Timer noch nicht so ganz verstanden hast, hier ist mal ein Beispiel

Code: Alles auswählen

 
procedure TForm1.Button1Click(Sender: TObject);
begin
  index := 1;
  Timer1.Enabled := True;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize();
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
var
  W1, W2, //Würfel1 Würfel2
  Res: integer; //Ergebnis
begin
  W1 := Random(6) + 1;
  W2 := Random(6) + 1;
  W1Img.Picture.LoadFromFile(Format('/PFAD/Image%d.png', [W1]));
  W2Img.Picture.LoadFromFile(Format('/PFAD/Image%d.png', [W2]));
 
  //Auswertung hier einfügen
 
  Inc(index);
  if index = 24 then
  begin
    Timer1.Enabled := False;
    //Hier code einfügen der nach dem letzten durchlauf ausgeführt werden soll
  end;
end;   

Antworten