Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   TThread und Rückgabe an Formular (https://www.delphipraxis.net/180807-tthread-und-rueckgabe-formular.html)

tofse 19. Jun 2014 08:52

TThread und Rückgabe an Formular
 
Hallo,
ich beschäftige mich gerade mit TThread, das funktioniert bisher ganz gut, nur frage ich mich, wie ich am besten eine Kommunikation mit dem Formular hinbekomme.
Im Thread werden Dateien kopiert. Im Hauptformular soll ein Fortschrittsbalken angezeigt werden und der Dateiname, der gerade kopiert wird.

Mit synchronize funktioniert das ja, aber in verschiedenen Tutorials habe ich gelesen, dass man das nicht machen würde. Das wäre ja pro Schleifendurchlauf im Thread ein Aufruf von synchronize, der jedesmal den Thread kurz unterbrechen würde.
Wie sieht es denn mit eigenen Events aus? Im Internet habe ich dazu gar nichts gefunden. Also das Definieren von einem Event im Thread, z.B. onFileCopied, worauf ich im Hauptformular reagieren würde. Das wäre der Weg gewesen, den ich ohne Nachlesen spontan genommen hätte, aber wie gesagt, da ich dazu gar nichts gefunden habe, weiß ich jetzt auch nicht, ob "man das nicht macht"?

Gruß und schönen Feiertag
Christof

Bjoerk 19. Jun 2014 09:04

AW: TThread und Rückgabe an Formular
 
Ei sah mo, hann ihr heid kä Feierdah? :-D

Wenn ein Thread mit VCL Komponenten kommuniziert kommt man meines Wissens nicht um ein Synchronize herum. Was du machen könntest wäre das Evnet z.B. nur 11 mal aufzurufen (0%, 10%, 20%, .. 80%, 90%, 100%).

Gruß aus Dingmatt via Monnem.

Mavarik 19. Jun 2014 09:19

AW: TThread und Rückgabe an Formular
 
Hi!

Natürlich brauchst Du das nicht bei jedem Schleifendurchlauf ein Syncornize zu machen, aber Du kannst auch einfach an Dein Formular ne Message senden.

Mavarik

Delphi-Quellcode:
CONST
  WM_Sync   = WM_User + 100;
  SM_MSG    = 1; // Ganzen Text
  SM_Prozent = 2; // Nur %

type
  PSyncMSG = ^TSyncMSG;
  TSyncMSG = record
               MSG : String[255];
               PZ : Integer;
             end;

  TMaifForm = Class(TForm)
    private
         procedure MySyncronize(var MSG: TMessage); message WM_Sync;

  end;

procedure TMyThread.Execute;
Var
  MyMessage           : PSyncMSG;
  I                   : Integer;
begin
  // ...
  New(MyMessage);

  MyMessage^.MSG := 'Hey ich bearbeite gerade: "Cool.pdf"';
  MyMessage^.PZ := 7;

  Postmessage(MainForm.Handle,WM_Sync,SM_MSG,LParam(MyMessage));

  for i:=0 to 100 do
    begin
      if I mod 10 = 0 then
        begin
          New(MyMessage);

          MyMessage^.MSG := '';
          MyMessage^.PZ := i;

          Postmessage(MainForm.Handle,WM_Sync,SM_Prozent,LParam(MyMessage));
        end;
    end;
  // ...
end;

procedure TMainform.MySyncronize(var MSG: TMessage);
var
  SyncMSG : PSyncMSG;
begin
  SyncMSG := PSyncMSG(MSG.LParam);

  Case MSG.WParam of
    SM_MSG    : begin
                   Label1.Caption := SyncMSG^.MSG;
                   Processbar1.Position := SyncMSG^.PZ;
                 end;
    SM_Prozent : begin
                   Processbar1.Position := SyncMSG^.PZ;
                 end;
  end;

  Dispose(SyncMSG);
end;

mjustin 19. Jun 2014 10:27

AW: TThread und Rückgabe an Formular
 
Zitat:

Zitat von tofse (Beitrag 1262856)
Mit synchronize funktioniert das ja, aber in verschiedenen Tutorials habe ich gelesen, dass man das nicht machen würde. Das wäre ja pro Schleifendurchlauf im Thread ein Aufruf von synchronize, der jedesmal den Thread kurz unterbrechen würde.

Neuere Delphi Versionen enthalten die Methode TThread.Queue, die im Unterschied zu Synchronize den Thread nicht sofort blockiert (sondern erst zu einem späteren Zeitpunkt). Queue legt den eigenen Methodenaufruf in eine Warteschlange und gibt die Kontrolle sofort an den Thread zurück. Im Haupthread wird dann "später" diese Queue abgearbeitet. Eine Garantie dafür gibt es aber nicht, z.B. falls beim Beenden des Programms noch Einträge in dieser Queue sind.

Mschmidt 19. Jun 2014 12:53

AW: TThread und Rückgabe an Formular
 
Ich verwende dazu Methodenaufrufe:

Delphi-Quellcode:
type
  TMainProc = procedure (<Parameter>) of object;

type
  TMain = Class(TForm)
...
  procedure Aktualisiere(<Parameter>);
...
  procedure StartThread;
end;

Type
  TMeinThread = Class(TThread)
  fMainProc :TMainProc;
  procedure Execute;
  constructor Create(MainProc:TMainProc);
end;

Constructor TMeinThread.Create;
begin
  ...
  fMainProc:= MainProc;
...
end;

procedure TMeinThread.Execute;
begin
  while not terminated do begin
  if (<Zähler>) and (assigned(fMainProc)) then
    synchronize ( begin fMainProc(<Parameter>)end;); // anonyme Methode
  ...
end;

procedure TMain.StartThread;
begin
  TMeinThread.create(Aktualisiere);
  ...
end;

procedure TMain.Aktualisiere(<Parameter>);
begin
  // dieser code wird aus dem Thread aufgerufen
...
end;
grüsse Mschmidt

tofse 19. Jun 2014 16:46

AW: TThread und Rückgabe an Formular
 
Hallo,

vielen Dank für die vielen Tipps.
Zu meiner Frage bzgl. Events hat sich noch niemand geäußert.
Ich habe es mal so versucht:

Delphi-Quellcode:
TCopyErrorEvent = procedure(Sender: TObject;Datei:String;Fehler:String) of Object;
Das hat funktioniert.
Nur wie gesagt, im Netz habe ich zu dieser Möglichkeit, Rückmeldung ans Formular zu geben, gar nichts gefunden. Deshalb: macht man das nicht, aus irgendeinen Grund, wie Performance oder hängt der Thread dann auch kurz?

Danke

Mschmidt 19. Jun 2014 16:51

AW: TThread und Rückgabe an Formular
 
Selbstverständlich macht man das, ansonsten wäre ja die methode synchronize obsolet,oder?
Dem thread ist das letztendlich egal. Das gibt auch keine Fehler oder sonst was, es sei den, du baust falsch....
Cheers mschmidt

Blup 19. Jun 2014 17:12

AW: TThread und Rückgabe an Formular
 
Events so wie du sie verwendest, dürfen vom Thread nur mit Synchronize aufgerufen werden.
Synchronize bedeuted, der Thread muss Anhalten, wenn der Hauptthread mal nichts zu tun hat führt er das Event aus, danach wird der Thread wieder aufgeweckt.

Der Vorschlag mit Postmessage ist da deutlich besser.

tofse 19. Jun 2014 17:23

AW: TThread und Rückgabe an Formular
 
Ah, ok, habs verstanden.

Danke

himitsu 19. Jun 2014 17:30

AW: TThread und Rückgabe an Formular
 
Zitat:

Zitat von Blup (Beitrag 1262914)
Events so wie du sie verwendest, dürfen vom Thread nur mit Synchronize aufgerufen werden.
Synchronize bedeuted, der Thread muss Anhalten, wenn der Hauptthread mal nichts zu tun hat führt er das Event aus, danach wird der Thread wieder aufgeweckt.

Der Vorschlag mit Postmessage ist da deutlich besser.

Nja, der Vergleich hinkt etwas.

Also, grundsätzlich dürfen Zugriffe auf die VCL (Delphi-GUI) nur aus dem Hauptthread erfolgen.
Synchronize nimmt die Funktion und führt sie im Hauptthread aus, wobei das natürlich so lange warten muß, bis der Haupthtead mal Zeit und Lust dafür hat.
Synchronize wartet mit der Ausführung, bis die übergebene Funktion fertig ist und erst dann läuft der Thread weiter.

Queue übergibt das auch an den Hauptthread, genau wie Synchronize, nur kehrt das sofort zurück und lässt den thread weiterarbeiten. Der Hauptthread führt aber auch da die Prozedur erst dann aus, wenn er kann.

Delphi-Referenz durchsuchenTThread.Synchronize -> MSDN-Library durchsuchenSendMessage
Delphi-Referenz durchsuchenTThread.Queue -> MSDN-Library durchsuchenPostMessage

Wenn du also das Synchronize-Equivalent "SendMessage" verwendet hättest, dann würde der Thread ebenfalls warten müssen, bis die Message verarbeitet wurde. :angel:


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:28 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz