Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Mehrere Threads nacheinander ausführen (https://www.delphipraxis.net/67055-mehrere-threads-nacheinander-ausfuehren.html)

Sascha L 8. Apr 2006 20:18


Mehrere Threads nacheinander ausführen
 
Hallo,

ich steh irgendwie auf'm Schlauch. Habe jetzt den ganzen Tag hier etliche Beiträge bzgl. Threads durchgelesen, konnte mein Problem aber immernoch nicht lösten :(

Ich möchte mehrere Threads NACHEINANDER ausführen.

D.h. erst wenn der erste Thread fertig ist, soll der 2. Thread ausgeführt werden... usw.

Wenn ich mit MeinThread.WaitFor arbeite, klappt das auch, aber während ein Thread ausgeführt wird, ist meine Anwendung eingefroren. Das darf aber nicht sein, da der Thread ständig etwas ins Caption eines Labels schreibt.

Wenn ich WaitForSingleObject(MeinThread,IFINITE) nutze, dann wird mein Thread nicht ausgeführt und meine Anwendung hängt bis ins unendliche.

Kann mir jmd. kurz den Code dafür geben, damit es klappt?

Ich habe einen dynamischen Thread-Array. Über eine for-Schleife führe ich "Resume" für einen Thread nach dem anderen aus. Aber da nicht alle Threads gleichzeitig ausgeführt werden sollen, was ja so passieren würde, soll er erst warten, bis der eine Thread zu ende ist, bevor er mit der for-Schleife weiterfährt und somit dann den nächsten Thread startet.

Gruß
Sascha

SirThornberry 8. Apr 2006 20:20

Re: Mehrere Threads nacheinander ausführen
 
du kannst dafür das OnTerminate des Thread nutzen bzw. kannst du ja innerhalb des Threads auch selbst ein Event auslösen in dem du dann den nächsten Thread startest.

DataCool 8. Apr 2006 22:55

Re: Mehrere Threads nacheinander ausführen
 
Hi,

SirThornberry hat absolut recht, dann müßtest Du Die eine procedure Schreiben die Du dem OnTerminate des Threads zuweist, dann kannst Du in dieser Procedure den nächsten Thread starten.

Was mich allerdings wundert :

Du willst mehere Threads verwenden, diese aber nur hintereinander ausführen ?
Und das Hauptprogramm wartet solange ?

Der Sinn/Vorteil von Threads ist doch, das diese parallel im Hintergrund arbeiten können !
Ich kann ja noch nachvollziehen das Thread 2 erst starten darf, wenn Thread 1 zu Ende ist,
weil Thread 2 z.b. Daten von Thread 1 benötigt.
Aber warum im Hauptprogramm auf die Threads warten ?

So wie Du das bis jetzt beschrieben hast, werden Dir die Threads null Vorteil bringen.

Gruß Data

Sascha L 9. Apr 2006 09:39

Re: Mehrere Threads nacheinander ausführen
 
Hm, dann muss ich einiges umschreiben. Mal gucken ob das klappt. Danke.


Warum ich die nacheinander aufrufen will?

Ich habe eine sehr rechenintensive Suche, die ich gerne in einen Thread auslagern möchte, damit die Hauptanwendung noch reagieren kann.

Die Threads kann ich nicht gleichzeitig ausführen, weil es dann elendig langsam werden würde, da die Festplatte hier der Flaschenhals ist. Ich kann ja nicht gleichzeitig c:\, d:\ und e:\ nach Dateien suchen. Da wird der Lesekopf ja total verrückt :D

EDIT:

Hab jetzt einfach die Aufrufe der Threads in einen eigenen Thread gepackt, und schon klappt es, dass die Hauptanwendung weiterhin reagiert :)

EDIT2:

Das klappt doch nicht. Da führt er immer nur einen Thread aus und die anderen beachtet er gar nicht :(

Sascha L 9. Apr 2006 12:12

Re: Mehrere Threads nacheinander ausführen
 
Das kann doch einfach nicht angehen :(

Delphi-Quellcode:
   for i := 0 to Length(SearchThread) - 1 do begin
    SearchThread[i].Resume;
    SearchThread[i].WaitFor;
    SearchThread[i].Free;
     end;
Wenn SearchThread eine Länge von 2 hat, d.h. es gibt 2 Threads, dann führt er nur einen richtig aus.

Den ersten führt er aus (rückwärts, d.h. er fängt mit dem letzten an, hat wohl was mit der Compiler-Optimierung zu tun), warte brav bis er zu ende ist und gibt ihn frei. Danach führt er den zweiten aus, aber beendet ihn sofort ohne den Code von Execute auszuführen :(

Hawkeye219 9. Apr 2006 12:19

Re: Mehrere Threads nacheinander ausführen
 
Kleiner Denkfehler!

Er führt schon den ersten aus und gibt den dann frei. Danach gibt es aber keinen zweiten mehr in der Liste...
Lasse die Schleife einfach mal rückwärts laufen.

Gruß Hawkeye

Sascha L 9. Apr 2006 12:21

Re: Mehrere Threads nacheinander ausführen
 
Danke für den Tipp, aber leider funktionert es auch nicht. Er führt trotzdem nur den 2. Thread aus. Oder bei Dreien nur den dritten.

SirThornberry 9. Apr 2006 12:45

Re: Mehrere Threads nacheinander ausführen
 
wenn du ein Array von Thread hast dann so:
Delphi-Quellcode:
//Thread erstellen
for i := 0 to length(ThreadArray) - 1 do
begin
  ThreadArray[i] := TThread.Create(True);
  ThreadArray[i].OnTerminate := ThreadTerminateProc;
end;
fCurrThreadIndex := 0;
ThreadArray[fCurrThreadIndex].Resume;
[...]
procedure TForm1.ThreadTerminateProc(Sender: TObject);
begin
  inc(fCurrThreadIndex);
  if fCurrThreadIndex < Length(ThreadArray) then
    ThreadArray[fCurrThreadIndex].Resume;
end;
Ist ungetestet sollte aber die Vorgehensweise verdeutlichen...

Sascha L 9. Apr 2006 13:04

Re: Mehrere Threads nacheinander ausführen
 
Danke, aber das klappt auch nicht.

Ich geb es auf :(

Das kann doch einfach nicht wahr sein, egal was ich mache, er fürt nur einen Thread aus und die anderen beendet er sofort.

DataCool 9. Apr 2006 13:07

Re: Mehrere Threads nacheinander ausführen
 
Dann zeig uns mal Deinen aktuellen Source.
Eigentlich hat SirThornberry schon alles richtig erklärt.

Gruß Data

Sascha L 9. Apr 2006 13:33

Re: Mehrere Threads nacheinander ausführen
 
Also:

Ich habe eine ChecklistBox, wo alle Festplatten/Partitionen aufgelistet werden.

Dann habe ich einen Record:

Delphi-Quellcode:
type
  TSelectedDrives = record
    Drive: string;
    Selected: Boolean;
  end;
Und davon dann natürlich einen Array, der so lang ist, wie es Festplatten/Partitionen gibt.

Mit einer Schleife überprüfe ich dann, welche Laufwerke ausgewählt sind (checked) und setzte dann im Array "Selected" auf true.

Das funktioniert alles 100% richtig.

Dann habe ich noch die Klasse TSearchThread mit folgender Execute-Prozedure und folgendem Create-Constructor:

Delphi-Quellcode:
constructor TSearchThread.Create(path:string);
begin
   fpath:=path;
   inherited Create(true);
end;

procedure TSearchThread.Execute;
  var
i:integer;
liste: TStringList;
begin
   liste := TStringList.Create;
   GetFilesInDirectory(fpath,'*.exe',liste,true,true); // Funktion hier aus der CodeLibary
   frmSearchdlg.Memo1.Lines.AddStrings(liste);
   liste.Free;
end;
Ja ich müsste eigentlich mit Synchronize arbeiten, aber das tut jetzt ja nichts zur Sache... :D

Dann habe ich noch einen Thread der dann alle SearchTreads nacheinander ausführen soll (s. obere Posts).

Und natürlich noch der Code für den SearchThread-Array:

Delphi-Quellcode:
SetLength(SearchThread,0);
   for i := 0 to Length(SelectedDrives) - 1 do begin
     if SelectedDrives[i].Selected then begin
       SetLength(SearchThread,Length(SearchThread)+1);
       SearchThread[Length(SearchThread)-1] := TSearchThread.Create(SelectedDrives[i].Drive);
       SearchThread[Length(SearchThread)-1].OnTerminate := ThreadTerminateProc;
     end;
   end;
   Threads := TThreads.Create(false); // Dieser Thread macht dann SearchThread[i].Resume
   Threads.FreeOnTerminate := true;
Der SearchThread-Array ist auch korrekt. Wie gesagt, wird aber immer nur der letzte von allen SearchThreads ausgeführt.

SirThornberry 9. Apr 2006 13:41

Re: Mehrere Threads nacheinander ausführen
 
und wie sieht die Execute-Methode von deinem TThreads aus? Auch die ThreadTerminateProc währe interessant. Im prinzip hast du ja nur den Source gepostet welcher die Threads creiert aber nicht den relevanten source welcher zeigt wie du nach Beendigung (ThreadTerminateProc) den nächsten Thread startest und auch nicht wie du dir merkst welches der nächste Thread ist (TThreads.Execute?)

Im übrigen hab ich hier noch einen Fehler gefunden:
Delphi-Quellcode:
Threads := TThreads.Create(false); // Dieser Thread macht dann SearchThread[i].Resume
Threads.FreeOnTerminate := true;
Diese stelle ist recht riskannt. Denn du startest den Thread und setzt danach erst "FreeOnTerminate := true". Theoretich kann zu diesem Zeitpunkt der Thread aber schon abgearbeitet sein.

Sascha L 9. Apr 2006 13:45

Re: Mehrere Threads nacheinander ausführen
 
Der Code, der dir nun fehlt, ist der, den du gepostet hast.

Ich habe deinen letzten Code verwendet und damit wird nur der letzte ausgeführt. Die anderen Codes habe ich nicht, da überschrieben.

Aber z.B. bei Post #5 Habe ich den Code von Threads.Execute.

Ich habe dort schon alles ausprobiert. von while über repeat until. Und habe da Überprüfung gemacht, ob der Thread1 beendet ist oder einen ReturnValue zurück gibt bevor er weiter machen darf. Habe dort mit WaitForSingleObject gearbeitet. Einfach ALLES.

Es werden auch ALLE Threads gestartet, aber es werden ALLE bis auf den letzten auch sofort wieder beendet, ohne dass deren Execute ausgeführt wird. Das versteh ich einfach nicht.

edit:

vielleicht sollte ich einfach das hier:
Delphi-Quellcode:
procedure TSearchThread.Execute;
  var
i:integer;
liste: TStringList;
begin
   liste := TStringList.Create;
   GetFilesInDirectory(fpath,'*.exe',liste,true,true); // Funktion hier aus der CodeLibary
   frmSearchdlg.Memo1.Lines.AddStrings(liste);
   liste.Free;
end;
dahingehend abändern, dass ich nicht nur ein Laufwerk übergebe, sondern die Liste mit allen ausgewählen Laufwerken und dann dort eine Schleife einbaue, die dann nacheinander alle Laufwerke durchsucht. Dann bräuchte ich auch nur noch einen Thread und keinen Array..

SirThornberry 9. Apr 2006 13:50

Re: Mehrere Threads nacheinander ausführen
 
der Source von Post#5 passt ja aber nicht zu der OnTerminate-Methode. Denn bei Post5 startest du die Threads in einer Schleife. Bei der OnTerminateMethode wird der nächste Thread eben im OnTerminate gestartet. Zudem brauchst du dann eigentlich die klasse TThreads nicht.

Im übrigen finde ich die Methode mit einem Thread (also ohne Array) bedeutend sinnvoller. Auch die Aktuallisierung des Memos solltest du syncron durchführen (ansonsten kommen teilweise unerklärliche fehler).

Sascha L 9. Apr 2006 13:53

Re: Mehrere Threads nacheinander ausführen
 
Beides gleichzeitig habe ich nicht genutzt. Ich habe einmal deinen Code ausprobiert mit OnTerminate und davor hatte ich eine ganz andere Variante (#5).

"Threads" ist dadurch entstanden, dass ich vor über die Hauptanwendung mit einer Schleife alle SearchThreads nacheinander abarbeiten wollte und dort dann auch mit WaitFor bzw. WaitForSingleObject gearbeitet habe. Dadurch fror aber während der Suche die Hauptanwendung ein. Das habe ich ganz oben auch geschrieben.

edit:

ja das werde ich nun auch wohl so machen. Das mit Synchronize habe ich ja oben auch geschrieben, dass ich das weiß und noch mache :D

Danke für deine Mühen ;)

SirThornberry 9. Apr 2006 13:56

Re: Mehrere Threads nacheinander ausführen
 
ich hab das mit dem Syncronize nur nochmal geschrieben um zu verdeutlichen das dein Fehler eventuell auch daher kommt (weil eben ohne Syncronisierung teilweise unerklärliche Dinge passieren). Wobei mich schon wundert das die Methode mit den Arrays nicht funktioniert. Da aber die Variante mit einem Thread bedeutend sinnvoller ist, ist es überflüssig da den Fehler weiter zu suchen anstelle das ganze sinnvoll umzubauen (eben auf einen Thread)


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 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 by Thomas Breitkreuz