AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Probleme beim Warten auf 2 Threads

Offene Frage von "RWarnecke"
Ein Thema von RWarnecke · begonnen am 26. Nov 2006 · letzter Beitrag vom 11. Dez 2006
Antwort Antwort
Seite 2 von 2     12   
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#11

Re: Probleme beim Warten auf 2 Threads

  Alt 26. Nov 2006, 15:06
Hallo Rolf.

Das WaitFor im Hauptthread der Anwendung einzubaue ist nicht sinnvoll. Damit konstruiert du genau das, was du zu vermeiden versuchst - das "Hängenbleiben" deiner Anwendung. Es bleibt also nichts anderes, als die Threads für sich separat arbeiten zu lassen und über eine Ereignisbehandung bzw. Signale zu kommunizieren, um damit eben nicht aktiv zu warten.

Ich möchte daher noch eine andere Läsung vorschlagen: Hast du dir die Delphi-Hilfe dazu einmal angesehen?
  • Warten, bis ein Thread vollständig ausgeführt ist
  • Warten, bis eine Aufgabe ausgeführt ist
Sehr angenehm kann man auch mit Hilfe des OnTermine-Ereignisses arbeiten. Die Delphi-Hilfe gibt folgende Information zum Ereignis OnTerminate:
Zitat:
Das Ereignis OnTerminate wird ausgelöst, sobald die Methode Execute des Threads zurückgekehrt ist, aber bevor der Thread freigegeben wird.
Gruß,
Panthrax.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#12

Re: Probleme beim Warten auf 2 Threads

  Alt 26. Nov 2006, 15:18
Irgendwie klappt das nicht. Denn einer beiden Threads gibt kein True zurück, deshalb bleibt es in der repeat-Schleife hängen.

Zitat von Panthrax:
Ich möchte daher noch eine andere Läsung vorschlagen: Hast du dir die Delphi-Hilfe dazu einmal angesehen?
  • Warten, bis ein Thread vollständig ausgeführt ist
  • Warten, bis eine Aufgabe ausgeführt ist
Sehr angenehm kann man auch mit Hilfe des OnTermine-Ereignisses arbeiten. Die Delphi-Hilfe gibt folgende Information zum Ereignis OnTerminate:
Zitat:
Das Ereignis OnTerminate wird ausgelöst, sobald die Methode Execute des Threads zurückgekehrt ist, aber bevor der Thread freigegeben wird.
Ja, ich habe mir die Delphihilfe angesehen und wurde nicht richtig schlau draus. Deshalb habe ich diesen Weg gewählt. Könntest Du mir das bitte anhand meines Beispieles bitte erklären.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
C.Schoch

Registriert seit: 2. Jan 2006
Ort: Wüstenrot
235 Beiträge
 
Turbo Delphi für Win32
 
#13

Re: Probleme beim Warten auf 2 Threads

  Alt 26. Nov 2006, 16:37
Hi,
Du köntest auch per msgWaitForMultipleObjekts oder WaitForMultipleObjekts auf die Threads warten.

z.B. so:
Delphi-Quellcode:
  
Var
  dwWaitResult : DWORD;
  ThreadArray : array[0..1] of THandle; // Handle Array um auf Threads zu warten
begin
  SearchForCopy := TSearchCopy.Create(false);
  SearchForCopy.FreeOnTerminate := False;
  SearchForDelete := TSearchDelete.Create(false);
  SearchForDelete.FreeOnTerminate := False;
  ThreadArray[0] := SearchForCopy.Handle; // Handle Array füllen
  ThreadArray[1] := SearchForDelete;
  repeat
    // Auf Threads warten
    dwWaitResult := msgWaitforMultipleObjects(length(ThreadArray), ThreadArray, true, 100, QS_ALLINPUT);
    if dwWaitResult <> WAIT_OBJECT_0 then
    begin
       Application.ProcessMessages; // GUI aktualisieren
    end;
  until dwWaitResult = WAIT_OBJECT_0; // keinen Threads mehr zum warten
end;
Tschau Christian
Das System hofft auf Besserung
[Siemens]
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#14

Re: Probleme beim Warten auf 2 Threads

  Alt 26. Nov 2006, 16:52
Hallo Rolf.

Ich beschreibe dir hier das Konzept noch einmal etwas genauer. Im Anhang habe ich das Konzept in einem Beispielprojekt gezeigt.

Das Konzept für 2 Threads

Du willst auf die Beendigung zweier Threads warten. Dafür bietet sich das OnTerminate-Ereignis der Klasse TThread an. Die Ereignisbehandlungsroutine braucht die Informationen über
  • den Thread, der abgeschlossen ist
  • den anderen Thread, ob er noch läuft oder nicht.
Nun ist die Sache einfach. Aus der ersten Information kann geschlussfolgert werden, welcher Thread als beendet markiert werden kann. Das kann nicht mithilfe des Threads selbst passieren, da sich dieser nach Beendigung selbst freigibt (FreeOnTerminate = True). Aus der zweiten Information kann geschlussfolgert werden, ob beide Threads damit beendet sind.

Ein Beispiel

Im Beispiel habe ich die Klasse TSleepThread von TThread abgeleitet. Die Aufgabe ist eine bestimmte Zeit zu schlafen. Anschließend ist der Thread beendet. Wie lange geschlafen werden soll wird im Kontruktor angegeben. Ther Parameter CreateSuspended wird an den Kontruktor von TThread weitergereicht. Kurzfassung:
Delphi-Quellcode:
type
  TSleepThread = class(TThread)
  ...

constructor TSleepThread.Create(const Milliseconds: Cardinal; const CreateSuspended: Boolean);
Zum Formular habe ich 2 Variablen (Eigenschaften) hinzugefügt: FThread1 (Thread1) und FThread2 (Thread2). Beide sind von der Klasse TSleepThread. Diese Felder dienen nur zum Merken, ob ein Thread beendet ist (= nil) oder nicht (<> nil). Kurzfassung:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    private
    FThread1, FThread2: TSleepThread;

    published
    property Thread1: TSleepThread read FSleepThread1 write FSleepThread1;
    property Thread2: TSleepThread read FSleepThread2 write FSleepThread2;
  end;
Die Methode RunThreads initialisiert und startet die Threads. Kurfassung:procedure RunThreads; Der Kern liegt in der Methode DoTerminate. Diese wurde den erzeugten Threads dem Ereignis OnTerminate zugewiesen. Neben einer Ausgaberückmeldung setzt diese Methode die Merker Thread1 bzw. Thread2 auf Nil, wenn der zugehörige Thread beendet wurde. Wurden beide abgearbeitet, sind folglich beide Nil. Das ist also der Zustand, nach dem du gesucht hast. Kurzfassung:
Delphi-Quellcode:
procedure TForm1.DoTerminate(Sender: TObject);
begin
  { Merker setzten, dass ein Thread beendet wurde. }
  if Sender = Thread1 then Thread1:=nil else
  if Sender = Thread2 then Thread2:=nil;
  { Fall, dass beide Threads beendet wurden. }
  if not Assigned(Thread1) and not Assigned(Thread2) then...;
end;
Damit ergibt sich also nicht mehr das Problem, dass das Programm "hängt".

Viel Spaß beim ausprobieren mit dem Beispiel. Ich habe es so gestaltet, dass man die "Laufzeit" der Threads einfach in der Oberfläche einstellen kann.

Beispiel erstellt und getestet mit Delphi 7 Enterprise.

Gruß,
Panthrax.

[edit=Panthrax]Glatt den Anhang vergessen... Jetzt ist er dabei.[/edit]
Angehängte Dateien
Dateityp: rar auf_2_threads_warten_208.rar (1,7 KB, 21x aufgerufen)
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#15

Re: Probleme beim Warten auf 2 Threads

  Alt 26. Nov 2006, 18:45
Ersteinmal ein dickes Danke an Christian, den sein Code funktioniert schon mal, wenn auch nicht ganz mit der Performance, als wenn ich nach dem Aufruf einfach die OnClick-Procedure beende.

Auch ein nochmaliges Danke an Dich Panthrax für Deine ausführliche Beschreibung. Verstehe ich das soweit richtig, dass der Code der nach der Ausführung der beiden Threads ausgeführt werden soll in der DoTerminate-Procedure stehen muss ? Wenn ja, wäre das nicht ganz Sinnvoll, da der Start von den beiden Threads in einer For-Schleife steht.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#16

Re: Probleme beim Warten auf 2 Threads

  Alt 26. Nov 2006, 19:31
Schön, dass es dir gefällt.

Ob der Code, der nach Abschluss beider Threads ausgeführt werden soll, in der Ereignisbehandlungsroutine von OnTerminate stehen sollte oder nicht, kann ich nicht beurteilen. Fest steht, dass dort auf diesen Zustand reagiert werden kann. Sei es durch direktes Fortführen des Programmablaufs dort oder durch Anstoßen eines anderen Programmteils.

Ich würde sehr wahrscheinlich eine Routine schreiben, die diese sich anschließenden Aufgaben übernimmt. Um dir jedoch dabei helfen zu können, bäuchte man schon etwas genauere Angaben, als "steht in einer For-Schleife". Es bleibt die Frage: Was hat die For-Schleife damit zu tun?

Gruß,
Panthrax.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#17

Re: Probleme beim Warten auf 2 Threads

  Alt 27. Nov 2006, 09:49
Also, ich habe das ganze mal gestern Abend nach dem Beispiel von Panthrax in mein Programm versucht umzusetzen. Es hat leider nicht funktioniert. Ich muss doch meine ganze Struktur im Programm ändern.


Zitat von C.Schoch:
z.B. so:
Delphi-Quellcode:
  
Var
  dwWaitResult : DWORD;
  ThreadArray : array[0..1] of THandle; // Handle Array um auf Threads zu warten
begin
  SearchForCopy := TSearchCopy.Create(false);
  SearchForCopy.FreeOnTerminate := False;
  SearchForDelete := TSearchDelete.Create(false);
  SearchForDelete.FreeOnTerminate := False;
  ThreadArray[0] := SearchForCopy.Handle; // Handle Array füllen
  ThreadArray[1] := SearchForDelete;
  repeat
    // Auf Threads warten
    dwWaitResult := msgWaitforMultipleObjects(length(ThreadArray), ThreadArray, true, 100, QS_ALLINPUT);
    if dwWaitResult <> WAIT_OBJECT_0 then
    begin
       Application.ProcessMessages; // GUI aktualisieren
    end;
  until dwWaitResult = WAIT_OBJECT_0; // keinen Threads mehr zum warten
end;
Kann man diesen Sourcecode noch irgendwie performanter machen ? Er funktioniert, ist aber grotten langsam.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
C.Schoch

Registriert seit: 2. Jan 2006
Ort: Wüstenrot
235 Beiträge
 
Turbo Delphi für Win32
 
#18

Re: Probleme beim Warten auf 2 Threads

  Alt 27. Nov 2006, 21:11
Hi,
Warum langsam? bei mir funktionirt der recht schnell und gut. Die Threads sind ja von dieser Funktion unabhängig.
Solltest du allerdings aus dem Thread direkt auf ein Element der GUI zugreifen (Auch über Syncronize) dann dauert es natürlich bis zu 100 ms bis dein Code fortgesetzt wird.
Ich vermute du verwendest diesen Code in CopyandSync und aktualisierst bei jedem Durchlauf von FindFirst / FindNext den Text deiner Statusbar so wird höchstens alle 100ms eine Datei gefunden!
Das Stichwort heist hier Messages oder du setzt eine Variable im Thread/Hauptprogramm den du vor Application.ProcessMessages ausließt und in Statusbar schreibst.
Tschau Christian
Das System hofft auf Besserung
[Siemens]
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#19

Re: Probleme beim Warten auf 2 Threads

  Alt 10. Dez 2006, 12:35
Zitat von C.Schoch:
Hi,
Warum langsam? bei mir funktionirt der recht schnell und gut. Die Threads sind ja von dieser Funktion unabhängig.
Solltest du allerdings aus dem Thread direkt auf ein Element der GUI zugreifen (Auch über Syncronize) dann dauert es natürlich bis zu 100 ms bis dein Code fortgesetzt wird.
Ich habe es jetzt mal probiert, wenn ich den Wert von 100ms runtersetze auf 5. Dann geht es schneller.
Zitat von C.Schoch:
Ich vermute du verwendest diesen Code in CopyandSync und aktualisierst bei jedem Durchlauf von FindFirst / FindNext den Text deiner Statusbar so wird höchstens alle 100ms eine Datei gefunden!
Damit liegst Du richtig. Ich setze diesen Code in meinem Projekt CopyAndSync ein. Das auslesen der Dateien erfolgt aber nicht über FindFirst / FindNext, sondern über eine Unit aus dem Synchronisationstool Pegasus von Luckie.
Zitat von C.Schoch:
Das Stichwort heist hier Messages oder du setzt eine Variable im Thread/Hauptprogramm den du vor Application.ProcessMessages ausließt und in Statusbar schreibst.
Das mit der Variable oder Message verstehe ich da noch nicht ganz.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
C.Schoch

Registriert seit: 2. Jan 2006
Ort: Wüstenrot
235 Beiträge
 
Turbo Delphi für Win32
 
#20

Re: Probleme beim Warten auf 2 Threads

  Alt 11. Dez 2006, 00:28
Zitat von RWarnecke:
Ich habe es jetzt mal probiert, wenn ich den Wert von 100ms runtersetze auf 5. Dann geht es schneller.
Was meine Vermutung bekräftigt, dass du aus den Threads heraus auf die GUI zugreifst.

Zitat von RWarnecke:
Damit liegst Du richtig. Ich setze diesen Code in meinem Projekt CopyAndSync ein. Das auslesen der Dateien erfolgt aber nicht über FindFirst / FindNext, sondern über eine Unit aus dem Synchronisationstool Pegasus von Luckie.
Auch der benutzt Find First/Next

Zitat von RWarnecke:
Das mit der Variable oder Message verstehe ich da noch nicht ganz.
Ich übergebe dem Thread einen Pointer auf eine in meiner Hauptanwendung definierten String den ich dann einfach im Thread mit Meldungen fülle:
Delphi-Quellcode:
  // Im Hauptprog
  SearchForCopy := TSearchCopy.Create(false);
  SearchForCopy.FreeOnTerminate := False;
  SearchForCopy.Message := @MessageString;
Delphi-Quellcode:
  //im Thread
  Message^ := 'Kopiere Datei xyz';
Und setze dann diese Meldung alle 100ms in meine Anzeige:
if dwWaitResult <> WAIT_OBJECT_0 then
begin
Label1.Caption := MessageString;
Application.ProcessMessages; // GUI aktualisieren
end;
Frei getippt!

p.s.: Es scheint ein Problem mit meinem Code (vor allem mit dem fWaitAll) zu geben schau mal hier:msgWait... sollte aber nicht weiter schlimm sein.
Damit gehts.
dwWaitResult := WaitforMultipleObjects(length(ThreadArray), @ThreadArray, true, 100);
Tschau Christian
Das System hofft auf Besserung
[Siemens]
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:39 Uhr.
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