![]() |
Re: Probleme beim Warten auf 2 Threads
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?
Zitat:
Panthrax. |
Re: Probleme beim Warten auf 2 Threads
Irgendwie klappt das nicht. Denn einer beiden Threads gibt kein True zurück, deshalb bleibt es in der repeat-Schleife hängen.
Zitat:
|
Re: Probleme beim Warten auf 2 Threads
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; |
Re: Probleme beim Warten auf 2 Threads
Liste der Anhänge anzeigen (Anzahl: 1)
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
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:
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:
type
TSleepThread = class(TThread) ... constructor TSleepThread.Create(const Milliseconds: Cardinal; const CreateSuspended: Boolean);
Delphi-Quellcode:
Die Methode RunThreads initialisiert und startet die Threads. Kurfassung:
type
TForm1 = class(TForm) private FThread1, FThread2: TSleepThread; published property Thread1: TSleepThread read FSleepThread1 write FSleepThread1; property Thread2: TSleepThread read FSleepThread2 write FSleepThread2; end;
Delphi-Quellcode:
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:
procedure RunThreads;
Delphi-Quellcode:
Damit ergibt sich also nicht mehr das Problem, dass das Programm "hängt".
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; 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] |
Re: Probleme beim Warten auf 2 Threads
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. |
Re: Probleme beim Warten auf 2 Threads
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. |
Re: Probleme beim Warten auf 2 Threads
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:
|
Re: Probleme beim Warten auf 2 Threads
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. |
Re: Probleme beim Warten auf 2 Threads
Zitat:
Zitat:
![]() Zitat:
|
Re: Probleme beim Warten auf 2 Threads
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
// Im Hauptprog
SearchForCopy := TSearchCopy.Create(false); SearchForCopy.FreeOnTerminate := False; SearchForCopy.Message := @MessageString;
Delphi-Quellcode:
Und setze dann diese Meldung alle 100ms in meine Anzeige:
//im Thread
Message^ := 'Kopiere Datei xyz'; 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: ![]() Damit gehts.
Delphi-Quellcode:
dwWaitResult := WaitforMultipleObjects(length(ThreadArray), @ThreadArray, true, 100);
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:41 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