Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TThread - Synchronize läuft erst danach? (https://www.delphipraxis.net/43268-tthread-synchronize-laeuft-erst-danach.html)

Gina 31. Mär 2005 18:30


TThread - Synchronize läuft erst danach?
 
Hallochen,

ich hab da ein kleines Problem, wo ich mir hinterher wahrscheinlich an den Kopf schlage, aber momentan komm ich einfach nicht dahinter... :oops:

Ich habe einen Thread erzeugt, um dort eine function auszuführen, die etwas länger dauert. Genauer gesagt: in dieser function wird eine CD-RW formatiert. Ich klicke also im Menü des Hauptformulars auf einen Eintrag, um die Formatierung zu starten. Dann wird ein kleines Fenster angezeigt, wo die verbleibende Zeit erscheinen soll. Während Synchronize wird das kleine Fenster aktualisiert. Ich starte also den Thread (das klappt auch wunderbar), nur Synchronize wird erst aufgerufen, wenn die Formatierung beendet ist.

Mein Problem ist also: wie muss ich es anstellen, dass Synchronize während dessen ausgeführt wird?

Hier mal die entscheidenden Code-Schnipsel dazu:

Im HauptFormular:
Delphi-Quellcode:
type
  TMain = class(TForm)
  ...
  private
    { Private declarations }
    MyThread:TMyThread;
    procedure ThreadDone(Sender: TObject);

procedure TMain.CDRW1Click(Sender: TObject);
begin
  Main.Enabled := false;
  PBar.Show;
  if Application.MessageBox('Alle Dateien auf der CD werden glöscht! '
     +#13#10+ 'Möchten Sie fotfahren?',
     'Warnung!', MB_YESNO + MB_DEFBUTTON2) = IDYES then begin
  if MyThread = nil then
     with TMyThread.Create(PBar.Label1, Brennen.NeroDeviceHandle) do
     OnTerminate := ThreadDone;
  end;
end;

procedure TMain.ThreadDone(Sender: TObject);
begin
  PBar.Hide;
  Main.Enabled := true;
  Main.Show;
end;
PBar ist das kleine Fenster (ursprünglich war dort eine Progressbar, daher der Name ;)).

In der unit des Threads:
Delphi-Quellcode:
type
  TMyThread = class(TThread)
  private
    { Private declarations }
    L1: TLabel;
    NDH: NERO_DEVICEHANDLE;
    TimeA: Cardinal;
    procedure UpdateVCL; // Update ProgressBar
  protected
    procedure Execute; override;
    function EraseRW(Sender: TObject): Boolean;
  published
    constructor Create(Label1: TLabel; NeroDeviceHandle: NERO_DEVICEHANDLE);
  end;

constructor TMyThread.Create(Label1: TLabel; NeroDeviceHandle: NERO_DEVICEHANDLE);
begin
  L1 := Label1;
  NDH := NeroDeviceHandle;
  FreeOnTerminate := true;
  inherited Create(False);
end;

procedure TMyThread.Execute;
begin
  EraseRW(self);  //<--- das ist die eigentliche function, die so lange dauert
  while (Terminated = false) do begin
    Synchronize(UpdateVCL);
  end;
end;

procedure TMyThread.UpdateVCL;
begin
  L1.Caption := 'geschätzte Zeit: '+ FormatDateTime('mm:ss',ETime);
  L1.update;
end;
Ich kann ja schlecht EraseRW() in die while-Schleife setzen, also hab ich es davor gesetzt. Logischerweise wird die function nun zuerst abgearbeitet, bevor er in die while-Schleife kommt... Warum dass so läuft, ist mir also klar. Nur wie schreibe ich es, damit Synchronize zwischendurch ausgeführt wird?

Wie gesagt, ist wahrscheinlich ganz banal, aber ich würde mich sehr freuen, wenn ihr mir einen kleinen Denkanstoß geben könntet... ;)

Tausend Dank, Gina.

Luckie 31. Mär 2005 18:50

Re: TThread - Synchronize läuft erst danach?
 
Zitat:

Zitat von Gina
procedure TMyThread.Execute;
begin
EraseRW(self); //<--- das ist die eigentliche function, die so lange dauert
while (Terminated = false) do begin
Synchronize(UpdateVCL);
end;
end;

Ist ja auch irgendwie logisch oder? Das Synchronize wird ja erst aufgerufen, wenn die Funktion EraseRW zurückgekehrt ist. Dein Synchronize gehört, wenn dan in die Funktion EraseRW rein.

Gina 31. Mär 2005 19:15

Re: TThread - Synchronize läuft erst danach?
 
Hi Luckie,

ich hab ja gesagt, dass mir das klar ist, aber ich kann in die Function das Synchronize nicht reinpacken, da es ja im Wesentlichen nur eine Zeile ist... :/

Vielleicht könnte ich ja eine Variable setzen, wenn die function gestartet wurde und die function dann immer wieder in der Schleife aufrufen, nur dass ich die entscheidende Zeile nicht mehrfach ausführe... :gruebel:

Muss ich gleich mal probieren...

Thx, Gina.

tommie-lie 31. Mär 2005 19:30

Re: TThread - Synchronize läuft erst danach?
 
Wie sieht den EraseRW aus? Wenn das Löschen der RW über Nero eine atomare Funktion ist, die also solange nicht zurückkehrt bis alles fertig ist, kannst du im aufrufenden Thread solange nichts machen. Die Anzeige über die verbleibende Zeit müsste dann in einem weiteren Thread sein, sofern Nero ein irgendwie geartetes Callback zurückschickt.

SirThornberry 31. Mär 2005 19:33

Re: TThread - Synchronize läuft erst danach?
 
irgend eine callback muss die funktion haben denn woher weiß man sonst wieviel zeit noch verbleibt?

Luckie 31. Mär 2005 19:33

Re: TThread - Synchronize läuft erst danach?
 
Zitat:

Zitat von Gina
ich hab ja gesagt, dass mir das klar ist, aber ich kann in die Function das Synchronize nicht reinpacken, da es ja im Wesentlichen nur eine Zeile ist... :/

Äh, der Funktionsaufruf besteht aus einer zeile, aber die Funktion besteht bestimmt nicht aus einer Zeile.

Chewie 31. Mär 2005 19:36

Re: TThread - Synchronize läuft erst danach?
 
@Gina:

Du hattest doch in einem anderen Thread mal erwähnt, dass du vorher die benötigte Zeit abrufen kannst?
Dann könntest du damit (im Hauptthread!!) die Zeit runterzählen.

Gina 31. Mär 2005 20:28

Re: TThread - Synchronize läuft erst danach?
 
Ja, die benötigte Zeit ist bekannt. Die rufe ich vorher ab. Sorry, ich dacht nicht, dass die Info dafür wichtig wäre.

Die Idee mit dem Zeit-runter-zählen im Hauptthread ist gar nicht übel. Dann brauche ich ja gar kein Synchronize und dann kann der Thread solange arbeiten wie er will...

Werd ich gleich mal ausprobieren...

Vielen lieben Dank, Gina.

PS: @Luckie
Das geht leider nicht, da es eine Funktion der NeroApi.dll ist. Da kann ich nix reinbasteln...;)

tommie-lie 31. Mär 2005 20:53

Re: TThread - Synchronize läuft erst danach?
 
Zitat:

Zitat von Gina
Das geht leider nicht, da es eine Funktion der NeroApi.dll ist. Da kann ich nix reinbasteln...;)

EraseRW *ist* also atomar und die Zeit muss *vorher* ermittelt werden? Dann geht es gar nicht anders. Im abgespaltenen Thread wird EraseRW ausgeführt und der Hauptthread kann nur vorher die Zeit abfragen und runterzählen, im abgespaltenen Thread, der solange blockiert ist, bis EraseRW fertig ist, solange kann dieser Thread also keinen weiteren Code ausführen.

By the way: Das erklärt auch, warum diese Schätzungen meist so verdammt daneben liegen, wenn sie später never ever aktualisiert werden können :-?

Gina 31. Mär 2005 21:12

Re: TThread - Synchronize läuft erst danach?
 
Hi,

das funktioniert super. Ich wußte doch, dass es dafür bestimmt eine ganz einfache Lösung gibt. Ich danke Euch ganz dolle... :spin2:

Ja, das mit der Zeit ist wirklich nicht so genau. Er hatte noch ca. 2 Minuten über, als er fertig war. Aber das macht nix. Freut sich der User eben, wenns etwas schneller ging ;) Und bei etwa 10 Minuten Dauer, schaut man sowieso nicht so genau hin... :D

Vielen lieben Dank nochmal, Gina.


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