Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi OnTimer wird nicht ausgelöst (https://www.delphipraxis.net/133201-ontimer-wird-nicht-ausgeloest.html)

Chemiker 27. Apr 2009 20:21


OnTimer wird nicht ausgelöst
 
Hallo,

Delphi-Quellcode:
procedure TfrmExcelDateiExportieren.btPivotTabelleZeigenClick(Sender: TObject);
begin
  Timer1.Enabled:= TRUE;
  frmWarnhinweis.frmWarnung.Show;
  frmWarnhinweis.frmWarnung.Refresh;  
  FAbfrageClass.MSId:= '%';
  FAbfrageClass.MSErmitteln;
  Timer1.Enabled:= FALSE;
  frmWarnhinweis.frmWarnung.close;
end;
Mit dieser Procedure wird ein Form mit einer Gauge dargestellt. Gauge .Progress soll dann über einen Timer weitergestellt werden.

Delphi-Quellcode:
procedure TfrmExcelDateiExportieren.Timer1Timer(Sender: TObject);
begin
  frmWarnhinweis.frmWarnung.Gauge1.Progress:= frmWarnhinweis.frmWarnung.Gauge1.Progress+10;
  frmWarnhinweis.frmWarnung.Refresh;
end;
Leider wird das OnTimer-Ereignis aber nicht ausgelöst.

Wie kann man das ändern?

Bis bald Chemiker

Valle 27. Apr 2009 20:27

Re: OnTimer wird nicht ausgelöst
 
Blockiert irgendeine der Anweisungen in 'TfrmExcelDateiExportieren.btPivotTabelleZeigenCli ck' denn deine Anwendung? Wenn nicht, dann ist der Fehler ja gefunden, da du gleich anschließend den Timer ja wieder deaktivierst. Wenn doch, dann ist der Fehler eigentlich auch gefunden. *g* Solange der Hauptthread der Anwendung blockiert ist, wird auch der Timer nicht funktionieren. Das wäre dann ein Fall für Hier im Forum suchenThreading. ;-)

Mit freundlichen Grüßen,

Valle

Hobby-Programmierer 27. Apr 2009 20:35

Re: OnTimer wird nicht ausgelöst
 
Vielleicht hilft ja auch ein
Delphi-Quellcode:
application.ProcessMessages
an der richtigen Stelle der ersten Prozedur.

Chemiker 27. Apr 2009 20:40

Re: OnTimer wird nicht ausgelöst
 
Hallo,

@Valle:
mit FAbfrageClass.MSErmitteln wird eine Datenbankabfrage durchgeführt und weil das solange dauert, sollte ein Formular einen Warnhinweis ausgeben und Gauge weiter gezählt werden.

@Hobby-Programmierer:
mehre Stellen probiert, leider kein Effekt.


Bis bald Chemiker

Valle 27. Apr 2009 20:43

Re: OnTimer wird nicht ausgelöst
 
Dann brauchst du Threading. Die Datenbankabfrage wird deine Anwendung komplett blockieren, was auch den Aufruf eines Timers unmöglich macht. Du kannst nun entweder das Warte-Fenster in einen Thread auslagern (würde ich aber nicht machen), müsstest dann aber schauen, dass du keine Probleme mit der VLC bekommst, da sie nicht threadsicher ist. Ansonsten würde ich empfehlen, die Datenbankabfrage in einen Thread auszulagern. Dabei solltest du dich unbedingt noch informieren, ob deine Datenbank überhaupt threadsicher ist. Dabei kann ich dir aber leider nicht helfen; ich kann kein Delphi. 8)

Mit freundlichen Grüßen,

Valle

Hobby-Programmierer 27. Apr 2009 20:48

Re: OnTimer wird nicht ausgelöst
 
Ist das Timer-Event mit dem Timer verbunden? Ist der Interval zu gross gewählt, sprich : ist die Datenspeicherung schneller wie der Interval?

Valle 27. Apr 2009 20:59

Re: OnTimer wird nicht ausgelöst
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Hobby-Programmierer
Ist das Timer-Event mit dem Timer verbunden? Ist der Interval zu gross gewählt, sprich : ist die Datenspeicherung schneller wie der Interval?

... :gruebel: ...

Es funktioniert nicht! Der Timer wird nicht aufgerufen in der Zeit, da hilft jedes ProcessMessages
nichts. Kleines Beispiel im Anhang; zusammengeschustert aus dem, was ich noch kann.

Mit freundlichen Grüßen,

Valle

Chemiker 27. Apr 2009 21:14

Re: OnTimer wird nicht ausgelöst
 
Hallo,

Zitat:

Zitat von valle
Dabei kann ich dir aber leider nicht helfen; ich kann kein Delphi.

Wie?

@Hobby-Programmierer: der Timer ist richtig mit dem OnTimer-Event verbunden, mit verschiedenen Intervallen versucht, kein Ergebnis.

Bis bald Chemiker

Valle 27. Apr 2009 21:18

Re: OnTimer wird nicht ausgelöst
 
Zitat:

Zitat von Chemiker
Wie?


Ich habe mal vor einigen Jahren in einer AG in der Schule Delphi gelernt. Da ich aber recht schnell an unserem Lehrer vorbei war und mich auch eher für andere Sprachen interessierte, verlor ich Delphi schnell aus dem Auge und habe es jetzt schon ewig nicht mehr produktiv eingesetzt. Ich kann eben nur noch minimales Zeug in Delphi. ;-) Jetzt liegt mein Fokus auf Python und PHP, ab- und zu mal C++.

Mit freundlichen Grüßen,

Valle

bigben37 27. Apr 2009 21:26

Re: OnTimer wird nicht ausgelöst
 
delay ist dein Freund. Damit werden andere Prozesse weiterhin verarbeitet.

Valle 27. Apr 2009 21:32

Re: OnTimer wird nicht ausgelöst
 
Zitat:

Zitat von bigben37
delay ist dein Freund. Damit werden andere Prozesse weiterhin verarbeitet.

Das Sleep in meiner Anwendung war ja nur ein Beispiel. *g* Chemiker macht in dieser Zeit ja eine Datenbank-Abfrage, welche die entsprechende Zeit die mein sleep() verschlafen hat, mit suchen in der Datenbank verbringt. (Oder mit warten auf eine Antwort des Datenbank-Servers, das hängt eben von der DB ab)

Mit freundlichen Grüßen,

Valle

bigben37 27. Apr 2009 21:36

Re: OnTimer wird nicht ausgelöst
 
Mist :oops:

Aber eigentlich kann das verzögern ja nur von dieser Zeile kommen FAbfrageClass.MSErmitteln;, da die drei anderen Zeilen nur zum einfachen zeichnen oder eine Zuweisung sind. Also müssten wir diese Prozeure mal zu Gesicht bekommen. (Ich hoff, meine Argumetation ist wenigstens halbwegs richtig :mrgreen: )

Chemiker 27. Apr 2009 21:47

Re: OnTimer wird nicht ausgelöst
 
Hallo,

Delphi-Quellcode:
procedure TAbtfrageClass.MSErmitteln;
var
  I: integer;
begin
  with FpFIBDataSetAbfrage do
  begin
    Close;
    SelectSQL.Text:= 'SELECT DISTINCT mw_msid FROM mw_tabelle';
    GenerateSQLs;
    Open;  
    while not EOF do
    begin
        // Die MSId-Bezeichnung aus der Datenbank wird in einer StringList
        // gespeichert. Diese Bezeichung ist auch gleichzeitig die Spalten-
        // bezeichnung für die PIVOT-Tabelle.
      FMSListe.add(FieldByName('mw_msid').AsString);
      next;      
    end;
  end;
end;
das ist die Procedure. Damit werden alle Datensätze durchlaufen und das kostet Zeit. Das ist der Grund warum ein Fenster mit einer Gauge angezeigt werden soll.

Bis bald Chemiker

Satty67 28. Apr 2009 06:48

Re: OnTimer wird nicht ausgelöst
 
Nach "next" ein Application.ProcessMessages. Wobei das nicht bei jedem Schleifendurchlauf aufgerufen werden sollte, sondern nur alle x Durchläufe.

Falls die Variable i in der Schleife hochgezählt wird:
Delphi-Quellcode:
if (i mod 100) = 0 then Application.ProcessMessages
Statt einem Timer wäre es in meinen Augen auch elegant, MSErmitteln eine Procedure zu übergeben, die die ProgressBar oder Gauge aktualisiert. Die Procedure statt Application.ProcessMessages aufrufen, was innerhalb der Procedure erledigt würde.

Chemiker 28. Apr 2009 07:02

Re: OnTimer wird nicht ausgelöst
 
Hallo Satty67,

die Schleife wird nur 25 durchlaufen. Das Problem ist der SQL-Aufruf, weil er alle Datensätze durchläuft.

Bis bald Chemiker

nahpets 28. Apr 2009 10:21

Re: OnTimer wird nicht ausgelöst
 
Hallo,

Delphi-Quellcode:
procedure TAbtfrageClass.MSErmitteln;
var
  I: integer;
begin
  i := 0;
  with FpFIBDataSetAbfrage do
  begin
    Close;
    SelectSQL.Text:= 'SELECT DISTINCT mw_msid FROM mw_tabelle';
Application.ProcessMessages;
    GenerateSQLs; // Wie lange braucht der? Wenn lange, dann dahinter ein
Application.ProcessMessages;
    Open; // Solange der ackert, wird's vermutlich nichts mit dem Aktuallisieren der Gauge.  
Application.ProcessMessages;
    while not EOF do
    begin
        // Die MSId-Bezeichnung aus der Datenbank wird in einer StringList
        // gespeichert. Diese Bezeichung ist auch gleichzeitig die Spalten- 
        // bezeichnung für die PIVOT-Tabelle.
      FMSListe.add(FieldByName('mw_msid').AsString);
      next;      
      Inc(i);
      // Zeit- und datenmengenabhängig größeren oder kleineren Wert nehmen.
      If i Mod 100 = 0 then begin
        Application.ProcessMessages;
      end;
    end;
  end;
end;
Wie stehen die Start- und Endewerte für frmWarnhinweis.frmWarnung.Gauge1?
Woher weiß die Routine, wann sie den Endewert erreicht hat um ggfls. wieder von vorne anzufangen. Sind Start- und Endewert eventuell so gewählt, dass ein Progress + 10 eine so kleine Veränderung der Gauge liefert, dass der Fortschritt nur einfach nicht zu sehen ist?

Alternative: Lass den Timer weg und rufe die Methode
Delphi-Quellcode:
Timer1Timer(Sender: TObject);
in MSErmitteln auf:
Delphi-Quellcode:
procedure TAbtfrageClass.MSErmitteln;
var
  I: integer;
begin
  i := 0;
  with FpFIBDataSetAbfrage do
  begin
    Close;
    SelectSQL.Text:= 'SELECT DISTINCT mw_msid FROM mw_tabelle';
Application.ProcessMessages;
    GenerateSQLs; // Wie lange braucht der? Wenn lange, dann dahinter ein
Application.ProcessMessages;
    Open;  
Application.ProcessMessages;
    while not EOF do
    begin
        // Die MSId-Bezeichnung aus der Datenbank wird in einer StringList
        // gespeichert. Diese Bezeichung ist auch gleichzeitig die Spalten- 
        // bezeichnung für die PIVOT-Tabelle.
      FMSListe.add(FieldByName('mw_msid').AsString);
      next;      
      Inc(i);
      // Zeit- und datenmengenabhängig größeren oder kleineren Wert nehmen.
      If i Mod 100 = 0 then begin
        Timer1Timer(Nil); // Gaugeposition verändern.
        Application.ProcessMessages;
      end;
    end;
  end;
end;

sirius 28. Apr 2009 10:43

Re: OnTimer wird nicht ausgelöst
 
Lasst doch bitte einmal dieses ständige Application.ProcessMessages! Dafür ist es überhaupt nicht da. Wie weiter oben bereits erwähnt wurde, muss die gesamte Datenbankgeschichte in einen eigenen Thread. Ja, das ist ein wenig aufwendig aber der Anwender deines Programms wird es dir danken.

Hobby-Programmierer 28. Apr 2009 10:49

Re: OnTimer wird nicht ausgelöst
 
... vielleicht so?
Delphi-Quellcode:
procedure TAbtfrageClass.MSErmitteln;

  procedure Gauge_refresh(Value: Integer);
  begin
    frmWarnhinweis.frmWarnung.Gauge1.Progress:= frmWarnhinweis.frmWarnung.Gauge1.Progress+ Value;
    frmWarnhinweis.frmWarnung.Refresh;
    Application.ProcessMessages;
  end;
 
begin
  with FpFIBDataSetAbfrage do
  begin
    Close;
    SelectSQL.Text:= 'SELECT DISTINCT mw_msid FROM mw_tabelle';
    Gauge_refresh(10);
    GenerateSQLs; // Wie lange braucht der? Wenn lange, dann dahinter ein
    Gauge_refresh(10);
    Open; // Solange der ackert, wird's vermutlich nichts mit dem Aktuallisieren der Gauge.  
    Gauge_refresh(10);
    while not EOF do
    begin
        // Die MSId-Bezeichnung aus der Datenbank wird in einer StringList
        // gespeichert. Diese Bezeichung ist auch gleichzeitig die Spalten- 
        // bezeichnung für die PIVOT-Tabelle.
      FMSListe.add(FieldByName('mw_msid').AsString);
      next;      
      Gauge_refresh(5); // anpassen je nach Anzahl der Bezeichnungen
      end;
    end;
  end;
end;
[edit] und natürlich muss der Timer weg

blauweiss 28. Apr 2009 11:00

Re: OnTimer wird nicht ausgelöst
 
Zitat:

Zitat von sirius
Lasst doch bitte einmal dieses ständige Application.ProcessMessages! Dafür ist es überhaupt nicht da. Wie weiter oben bereits erwähnt wurde, muss die gesamte Datenbankgeschichte in einen eigenen Thread. Ja, das ist ein wenig aufwendig aber der Anwender deines Programms wird es dir danken.

Kann da nur zustimmen ! Application.ProcessMessages wird ja gerne als Allheilmittel empfohlen. Was fatal ist, wenn man nicht bedenkt, daß die GUI quasi parallel weiterarbeitet, inklusive FormClose, nochmaliger Aufruf einer Funktion über ButtonClicks etc.
Die nächste Frage ist schon vorprogrammiert -> "ich will mein Programm schliessen aber es tut sich nichts"....

Der saubere Weg ist ein Thread, der kontrolliert gestartet und beendet wird.

blauweiss

NormanNG 28. Apr 2009 11:18

Re: OnTimer wird nicht ausgelöst
 
Hi,

mal ein anderer Ansatz:

SQL-Code:
SelectSQL.Text:= 'SELECT mw_msid FROM mw_tabelle group by mw_msid';
Evtl. dann ein "Ich mach was"-Hinweis nicht mehr nötig?

Chemiker 29. Apr 2009 20:49

Re: OnTimer wird nicht ausgelöst
 
Hallo,

@nahpets:
Habe einige Zeitmessungen gemacht und es ist eindeutig der Befehl:

Delphi-Quellcode:
 Open;
Alle anderen Befehle und die Schleife verbrauchen kaum Zeit.
Der Startwert ist 0, der Endwert wird normalerweise nicht erricht. Wenn das Programm im Debugger-Modus (F7) wird die Gauge korrekt angezeigt.

@sirius:
Mit einem Thread in einer Datenbankabfrage habe ich noch nicht gearbeitet. Werde das ganze aber mal versuchen.

@Hoppy-Programmierer:
Bis zum Befehl: Open; wird die Gauge angezeigt, danach ist Stillstand und anschließend verschwindet das Form mit der Gauge.

@blauweiss:
Muss mich erst in die Thread - Problematik im Zusammenhang mit Datenbankabfragen einarbeiten.

@NormanNG:
Mit dieser SQL-Abfrage dauert die Abfrage um den Faktor 2-3 länger.


Gibt’s irgendwo ein Beispiel für eine SQL-Abfrage, bei der FIBPlus als Komponente und Firebird eingesetzt wird?

Bis bald Chemiker


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:29 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