Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Komisches Phänomen bei Threads. var array of meinthread. (https://www.delphipraxis.net/149019-komisches-phaenomen-bei-threads-var-array-meinthread.html)

Jackie1983 12. Mär 2010 13:46


Komisches Phänomen bei Threads. var array of meinthread.
 
Servus,

das ganze ist ein wenig schwer zu beschreiben, aber ich versuche es mal.
Also ich habe einen Hauptthread. Threadmain. Der erstellt und verwaltet x Threads. ThreadSub.
Threadmain und Threadsub laufen in einer while bis sie beendet werden.

Threadsub erstellt noch y Threads, ThreadJob. ThreadJob wird aber beendet wenn er seine Arbeit erledigt hat.

Es werden ca. 5-10 ThreadSub erstellt je nach CPU Core.
ThreadJob, werden nur 2-4 erstellt, je nach CPU Core.

Jetzt kommt es zum Problem.
So erstell ich aus dem Threadmain die Threadsubs
Delphi-Quellcode:
  //Erstellen
  SetLength(fThreadSub, 8);
  for i:=0 to Length(fThreadSub) do
    fThreadSub[i] := TThreadSub.Create;

  //.....

  //Freigeben
  for i:=0 to Length(fThreadSub) do
  begin
    fThreadSub[i].Terminate;
    FreeAndNil(fThreadSub[i]);
  end;
Wenn ich 8 Threads erstelle, ohne Probleme, kein Fehler.
Wenn ich 7 Threads erstelle, kommt beim beenden eine EAccessViolation
Wenn ich 6 Threads erstelle, ohne Probleme, kein Fehler.
Schon komisch

Erstelle ich das ganze per Var und stecke das Object in einer liste, klappt auch alles, auch bei 7 Threads
Delphi-Quellcode:
 
  for i:=0 to 8 do begin
    fThreadSub := TThreadSub.Create;
    fThreadSub.MaxThreads := 2;
    fThreadSubList.Add(fThreadSub);
  end;

  //....

  for i:=fThreadSubList.Count-1 downto 0 do begin
    fThreadSub := TThreadSub(fThreadSubList.Items[i]);
    fThreadSub.Terminate;
    fThreadSubList.Delete(i);
  end;
  FreeAndNil(fThreadSubList);
Um fehler zu vermeiden habe ich den Threads auch nur eine while schleife genommen ohne Variablen und sonst was,
selbst da kam der Fehler. Und bei einem Fehler hat mir FastMM4 nur müll angezeigt. Sachen die ich gar nicht im Projekt verwende.

Hatte schon mal jemand so ein Problem......
Oder habe ich eventuell doch unsauber programmiert?

Mfg

Uwe Raabe 12. Mär 2010 14:31

Re: Komisches Phänomen bei Threads. var array of meinthread.
 
Das geht ja gar nicht:

Delphi-Quellcode:
   
fThreadSub[i].Terminate;
FreeAndNil(fThreadSub[i]);
Das Terminate setzt nur das property Terminated auf true. Im Execute muss dieses dann abgefragt und die Methode verlassen werden. Nach ein paar Aufräumarbeiten ist der Thread dann beendet.

Mit dem FreeAndNil direkt hinter Terminate entziehst du dem Thread in den meisten Fällen seinen Speicherbereich bevor er sich beenden konnte.

Als Lösung auf die Schnelle würde ich zwei Schleifen daraus machen: die erste ruft nur Terminate auf, während die zweite für jeden Thread ein WaitFor aufruft und den Thread danach freigibt.

Es ist zwar aus deinem Code nicht ersichtlich, aber ich vermute, du erzeugst die Threads mit FreeOnTerminate=false. Alternativ kannst du die Threads auch mit FreeOnTerminate=true erzeugen und nach dem Terminate einfach den Array-Eintrag auf nil setzen:

Delphi-Quellcode:
   
//Erstellen
SetLength(fThreadSub, 8);
for i:=0 to Length(fThreadSub) do begin
  fThreadSub[i] := TThreadSub.Create;
  fThreadSub[i].FreeOnTerminate := true;
end;

//...
 
//Freigeben
for i:=0 to Length(fThreadSub) do
begin
  fThreadSub[i].Terminate;
end;

for i:=0 to Length(fThreadSub) do
begin
  fThreadSub[i].WaitFor;
  fThreadSub[i] := nil;
end;

Jackie1983 12. Mär 2010 14:54

Re: Komisches Phänomen bei Threads. var array of meinthread.
 
Zitat:

Zitat von Uwe Raabe
Das Terminate setzt nur das property Terminated auf true. Im Execute muss dieses dann abgefragt und die Methode verlassen werden. Nach ein paar Aufräumarbeiten ist der Thread dann beendet.

Das weis ich, so wird es ja auch gemacht. while not terminated do .....

Zitat:

Zitat von Uwe Raabe
Als Lösung auf die Schnelle würde ich zwei Schleifen daraus machen: die erste ruft nur Terminate auf, während die zweite für jeden Thread ein WaitFor aufruft und den Thread danach freigibt.

Wuste nicht das es ein WaitFor gibt. Lol ich habe bei einigen Threads per Variable die Funktion nach programmiert, und dabei gibt es die schon von haus aus....

dominikkv 12. Mär 2010 15:32

Re: Komisches Phänomen bei Threads. var array of meinthread.
 
Das geht auch noch einfacher... Threads besitzen eine Eigenschaft .FreeOnTerminate, die standardmäßig True ist. Ist dies der Fall geben sich die Threads selbstständig frei!

Jackie1983 12. Mär 2010 15:37

Re: Komisches Phänomen bei Threads. var array of meinthread.
 
Ok dann weis ich aber nicht wann die Threads beendet wurden.
Weil der Thread soll nicht abgebrochen werden, wenn das Programm geschlossen wird.

Heist wenn ein Thread einen langen job hat darf der Thread erst beendet werden wenn der Jon fertig ist
und demnach darf das Programm auch erst geschlossen werden wenn alle Threads beendet wurden.

dominikkv 12. Mär 2010 15:42

Re: Komisches Phänomen bei Threads. var array of meinthread.
 
Hier eignet sich das Ereignis .OnTerminate hervorragend


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