Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Prozessbar wärend Prozess laufen lassen


Jakane - Mi 11.07.12 10:30
Titel: Prozessbar wärend Prozess laufen lassen
Hallo liebe Delphi-Helfer :)

Mit eine Script lade ich mir Daten in meine Datenbank. Sind es nur wenige Datensätze, dann stört es keinen, aber bei 30.000 und mehr, kann das schon 2-3 Minuten dauern :-/
Allerdings springt der Timer, der die Prozessbar laufen lässt, gar nicht an, weil das Script die Prozedur blockiert :(


Delphi-Quelltext
1:
2:
3:
  Timer.Enabled:= True;
  IBScript.ExecuteScript;
  Timer.Enabled:= False;


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TfmHaupt.TimerTimer(Sender: TObject);
begin  // Interval = 10
  Prozessbar_einstellen(PB, 200, Zeit, 0);
  Inc(Zeit);
  if Zeit > 200 then Zeit:= 0;
end;

Wie kann ich meine Prozessbar sehen, wie sie läuft, wärend das Script läd?

Danke für die Hilfe :)

Moderiert von user profile iconNarses: Code- durch Delphi-Tags ersetzt
Moderiert von user profile iconNarses: Topic aus Dateizugriff verschoben am Mi 11.07.2012 um 11:28


bummi - Mi 11.07.12 10:37

Den Script in einem Thread ausführen? Ich kenne mich mit leider IB nicht aus ...


Jakane - Mi 11.07.12 10:39

user profile iconbummi hat folgendes geschrieben Zum zitierten Posting springen:
Ich kenne mich mit leider IB nicht aus ...

kannst auch jeden anderen, nicht beeinflussbaren Prozess nehmen, zB das versenden einer eMail

user profile iconbummi hat folgendes geschrieben Zum zitierten Posting springen:
Den Script in einem Thread ausführen?

was ist ein Thread?


bummi - Mi 11.07.12 10:52

http://www.michael-puff.de/Programmierung/Delphi/Tutorials/Threads_mit_Delphi.pdf
http://www.componentace.com/multi-thread-delphi.htm
http://wiki.delphigl.com/index.php/Tutorial_Multithreading

u.v.m.


Delete - Mi 11.07.12 10:54

Code der quasi parallel ausgeführt wird. Einfach mal Google bemühen. Es finden sich dazu recht viele Tutorials.


HelgeLange - Mi 11.07.12 15:35

Trotzdem weiss man nicht, wielange es dauern wird. Dadurch wird es schwer, eine progressbar dorthinzusetzen. Was du natürlich machen kannst : das script schiesst firebird events und du weisst, wo es gerade ist. Natürlich nicht zu oft :)
Die Events empfängst Du in deinem mainthread und nutzt die info um die progressbar abzuarbeiten


Jakane - Fr 13.07.12 10:00

Hab mir inzwischen einiges durchgelesen, aber irgendwas geht immernoch nicht:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
type
  // Definition
  TProzessbalken = class(TThread)
  private
    FProgressBar: TProgressBar;
  protected
    procedure Execute; override;
  public
    constructor Create(ProgressBar: TProgressBar);
  end;


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:
constructor TProzessbalken.Create(ProgressBar: TProgressBar);
begin
  // Erstellen
  FProgressBar:= ProgressBar;
  FreeOnTerminate := True;
  inherited Create(False);
end;

procedure TProzessbalken.Execute;
var
  i: Integer;
begin
  // Ausführen
  try
    for i := 1 to 100 do
    begin
      FuP_S._Prozessbar_einstellen(FProgressBar, 100, i, clRed);
      Sleep(100);
    end;
  except
    on e: exception do begin
      ShowMessage('Fehler im Parallel-Prozess.');
    end;
  end;
end;


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
  Prozessbalken: TProzessbalken;
begin
  Prozessbalken:= TProzessbalken.Create(PB);
  Prozessbalken.Resume; // Arbeiten
  IBSFTT.ExecuteScript;
  Prozessbalken.Suspend; // Pause


Bisher macht er nicht mehr als vorher auch...
Er läd das Script, aber der Balken bewegt sich nicht.

Weiss jemand was falsch ist? :(

Moderiert von user profile iconNarses: Code- durch Delphi-Tags ersetzt


Narses - Fr 13.07.12 10:19

Moin!

user profile iconJakane hat folgendes geschrieben Zum zitierten Posting springen:
Weiss jemand was falsch ist?
Fast alles... :? Du hast es genau verkehrt herum gemacht: die eigentliche (unsichtbare) Arbeit muss in den Thread, die GUI bearbeitest du im Haupt-Thread. Da kannst du die Progressbar z.B. mit einem einfachen TTimer weiterlaufen lassen. :idea:

Randproblem: Man darf aus Threads heraus nicht (unsynchronisiert) auf die VCL zugreifen, das knallt immer (früher oder später)! :mahn:

cu
Narses


Jakane - Fr 13.07.12 10:56

Jetzt versteh ich gar nichts mehr :(

Kann jemand mein Code umbauen, das es funktioniert?


Narses - Fr 13.07.12 11:24

Moin!

user profile iconJakane hat folgendes geschrieben Zum zitierten Posting springen:
Mit eine Script lade ich mir Daten in meine Datenbank. Sind es nur wenige Datensätze, dann stört es keinen, aber bei 30.000 und mehr, kann das schon 2-3 Minuten dauern
Das muss in den Thread, nicht das Weiterschieben der ProgressBar. :idea:

cu
Narses


Jakane - Fr 13.07.12 11:33

Moderiert von user profile iconNarses: Komplett-Zitat des letzten Beitrags entfernt.

Hilft grad nur bedingt weiter.
Wenn ich das Script.Execute in den Thread schieben, wie sag ich dann der Prozessbar wie lange die laufen muss? ohne das sie mit den nachfolgenden Ereignissen weiter macht?


bummi - Fr 13.07.12 11:51

Wie lange es dauert wird schwierig sein abzuschätzen, ich weiß nicht ob es bei Firebird Events o.ä. gibt, notfalls könnte man eine "Tabelle" mit Statusschritten füllen und die pollen, die Fertigstellung kannst Du über OnTerminate des Threads abfackeln


Narses - Fr 13.07.12 11:51

Moin!

user profile iconJakane hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich das Script.Execute in den Thread schieben, wie sag ich dann der Prozessbar wie lange die laufen muss?
Du weißt doch eh nicht, wie lange der Thread läuft, oder? :zwinker: Ansatz: Schätze die Laufzeit am Anfang ab, lass die ProgresBar laufen, wenn die ProgressBar das Ende erreicht hat, aber der Thread noch läuft, wieder am Anfang anfangen... Pech gehabt. :nixweiss: Genauer geht´s nicht. :?

user profile iconJakane hat folgendes geschrieben Zum zitierten Posting springen:
ohne das sie mit den nachfolgenden Ereignissen weiter macht?
Klar, alle weiteren Aktionen müssen in ein OnTerminate-Ereignis des Threads rein, solange der läuft, tut das Hauptprogramm nix (ausser die ProgressBar zu bewegen (per Timer) und auf sonstige Userinteraktionen (z.B. Fenster verschieben) zu reagieren). :idea:

cu
Narses

//EDIT: Nach der Idee von user profile iconbummi :beer: geht´s natürlich schon genauer, aber eine Schätzung wird das immer bleiben. :nixweiss: Die Frage ist halt, wie genau die wird. ;)


Jakane - Di 17.07.12 09:06

Danke Narses und auch alle anderen.
Hat zwar ewig gedauert eh ichs begriffen hab, aber jetzt gehts.

Und mit einer Programmweiten Varriablen brauch ich nur noch das Script in dem Thread haben :)


Jakane - Mo 23.07.12 10:12

Irgendwas scheint immernoch falsch zu sein :(


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
begin
  Database.Close;
  Database.Open;
  if not OpenDialog.Execute then EXIT;

  IBScript.Script.LoadFromFile(OpenDialog.FileName);
  _Parallel_Prozessbar(IBScript);
end;


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
type
  TProzessScript = class(TThread)
  private
    PIBScript: TIBScript;
  protected
    procedure Execute; override;
  public
    constructor Create(IBScript: TIBScript);
  end;


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure _Parallel_Prozessbar(IBScript: TIBScript);
var
  ProzessScript: TProzessScript;
begin
  ProzessScript:= TProzessScript.Create(IBScript);
  ProzessScript.Resume; // Arbeiten
end;


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TProzessScript.Execute;
begin
  ProzessFertig:= False;
  PIBScript.ExecuteScript;
  ProzessFertig:= True;
end;


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
constructor TProzessScript.Create(IBScript: TIBScript);
begin
  PIBScript:= IBScript;
  FreeOnTerminate := True;
  inherited Create(False);
end;


Der 1. Lauf klappt immer problemlos, aber wenn ich das das 2. mal aufrufe bekomm ich Fehlermeldungen.
Den Transactionsfehler bekomme ich auch wenn ich vorher mit PIBScript.Transaction auf Activ setze.

Weiss einer Rat?

Moderiert von user profile iconNarses: Code- durch Delphi-Tags ersetzt