Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Arbeiten mit TThreadList (https://www.delphipraxis.net/176021-arbeiten-mit-tthreadlist.html)

Captnemo 7. Aug 2013 18:40

AW: Arbeiten mit TThreadList
 
Zitat:

Zitat von Sir Rufo (Beitrag 1223858)
Zitat:

Zitat von Captnemo (Beitrag 1223857)
Daniel hatte es für mich mit seiner Antwort schon wie immer sehr treffend auf dem Punkt gebracht. :thumb::thumb:

Wann hat der denn hier geantwortet? :gruebel:

Oh mein Gott:twisted::twisted:

Meinte natürlich dich :-D:-D Verd*mt, hab euch glatt verwechselt. Wie peinlich :lol::lol:

Also, natürlich hast du es auf den Punkt gebracht. Großes Sorry

Captnemo 23. Jun 2014 12:24

AW: Arbeiten mit TThreadList
 
Hi, ich muß diese Thema noch mal aufwärmen, da ich da noch ein paar Probleme habe.

Also ich erzeuge mir eine TThreadList, die ich beim Beenden des MainThread entfernen möchte.

Delphi-Quellcode:
procedure Tfrm_main.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
  I: Integer;
  r: Cardinal;
begin
  for I := RS232ThreadList.Count-1 downto 0 do
  begin
    TComThread(RS232ThreadList[i]).StopListen;
    TComThread(RS232ThreadList[i]).Terminate;
    r:=WaitForSingleObject(TComThread(RS232ThreadList[i]).Handle, 1000);
    //ShowMessage(IntToStr(r));
  end;
end;

procedure Tfrm_main.FormCreate(Sender: TObject);
begin
  RS232ThreadList:=TObjectList.Create;
end;

procedure Tfrm_main.FormDestroy(Sender: TObject);
begin
  RS232ThreadList.Free;
end;
Sicherlich nicht korrekt, denn im FormDestroy kommt es beim RS232ThreadList.Free zu einer Exception, da die Thread noch nicht beendet sind.

Bzw. genau genommen, lande ich in System.Classes im Destructor TThread.Destroy beim CloseHandle;
Meine Annahme, die Threads in der ThreadList sind noch nicht beendet.

Wie mache ich es richtig? Ich muß ja im OnCanClose auf das Beenden der Threads warten.

Uwe Raabe 23. Jun 2014 12:43

AW: Arbeiten mit TThreadList
 
Zeig mal

a) wie du die Threads erzeugst (FreeOnTerminate?)
b) wie du die Liste erzeugst (OnwsObjects?)

Dejan Vu 23. Jun 2014 13:01

AW: Arbeiten mit TThreadList
 
Wieso wartest Du nur maximal eine Sekunde auf das Handle? Warte doch lieber, bis das Handle die Fahne oben hat, auch wenn's dauert...
Und falls es sich dabei um Threads handelt, würde ich mit 'WaitFor' noch warten, bis das Teil auch wirklich beendet ist und es dann ggf. explizit per Free freigeben (außer, das macht die ThreadListe selbst)

Captnemo 23. Jun 2014 13:29

AW: Arbeiten mit TThreadList
 
Mit OwnObject:=False funktionierts. FreeOnTerminate ist True.

Jetzt werden die Objecte (Thread) also freigegen, wenn die Liste freigegeben werden.
Aber eigentlich müßte es ja auch anders gehen.

Ist denn das mit Waitforsingleobject so korrekt? Was ist eigentlich der Rückgabewert von Waitforsingleobject? In meinem Fall habe ich immer 0 zurück bekommen.

Das mit 1000 Milisekunden ist erst mal zum Testen gewesen.

Mit WaitFor on OnCanClose bekomme ich immer die EThread-Exception "Das Handle ist ungültig(6)".

Der schöne Günther 23. Jun 2014 13:51

AW: Arbeiten mit TThreadList
 
Das ist die
Delphi-Quellcode:
TThreadList
aus
Delphi-Quellcode:
System.Classes
oder
Delphi-Quellcode:
System.Generics.Collections
, oder? Ich kann der nichts abgewinnen: Da fehlen elementarste Dinge wie ein
Delphi-Quellcode:
GetEnumerator()
und alles. Bist du sicher, dass du die brauchst? Ich hätte gedacht, dass du die RS232-Threads alle im Hauptthread erstellst und an die Liste dranhängst und ebenso dort auch die Liste wieder zumachen willst?

Ich nehme da einfach eine ganz "normale" Objektliste (
Delphi-Quellcode:
TObjectList
)- Soweit die
Delphi-Quellcode:
OwnsObjects = True
hat, ist die Freigabe der Liste mitsamt aller enthaltenen Threads so einfach wie ein
Delphi-Quellcode:
meineListe.Free();
Bsp:
Delphi-Quellcode:
program Project4;

{$APPTYPE CONSOLE}
{$R *.res}

uses
   System.SysUtils,
   System.SyncObjs,
   System.Classes,
   System.Generics.Collections;

const
   numThreads: Integer = 5;

var
   threadList: TObjectList<TThread>;
   threadNum: Integer;
   threadIterator: TThread;
   consoleCs: TSynchroObject;

//{$DEFINE OWNSOBJECTS}

procedure writeConsole(const line: String);
begin
   consoleCs.Acquire();
   try
      WriteLn(line);
   finally
      consoleCs.Release();
   end;
end;

function constructRunningThread(const threadNum: Integer): TThread;
begin
   Result := TThread.CreateAnonymousThread(
      procedure
      begin
         writeConsole('Thread ' + threadNum.ToString() + ' startet...');
         sleep(1000 + Random(4000));
         writeConsole('Thread ' + threadNum.ToString() + ' endet...');
      end
   );
   Result.FreeOnTerminate := {$IFDEF OWNSOBJECTS}False{$ELSE}True{$ENDIF};
   Result.Start();
end;

begin
   try
      consoleCs := TCriticalSection.Create();

      writeConsole('Erstelle und fülle Liste...');
      threadList := TObjectList<TThread>.Create(
         {$IFDEF OWNSOBJECTS}True{$ELSE}False{$ENDIF}
      );
      for threadNum := 0 to Pred(numThreads) do
         threadList.Add(constructRunningThread(threadNum));

      writeConsole('Baue Liste ab...');
      threadList.Destroy();
      writeConsole('Liste abgebaut');
      writeConsole('<Taste drücken>');
   except
      on E: Exception do
         WriteLn(E.ClassName, ': ', E.Message);
   end;

   ReadLn;
end.


// Roter Kasten:
Entweder ein TThread hat FreeOnTerminate = True und du fasst ihn nach dem Starten nicht mehr an(!) oder er hat es auf False und du gibst die TThread-Instanz selbst so frei wie du möchtest. Ich habe das mal versucht in das Beispiel zu packen: Du kannst das
Delphi-Quellcode:
{$DEFINE OWNSOBJECTS}
einmal auskommentieren und dir den Unterschied anschauen :-)

Uwe Raabe 23. Jun 2014 13:59

AW: Arbeiten mit TThreadList
 
Zitat:

Zitat von Captnemo (Beitrag 1263254)
Mit OwnObject:=False funktionierts. FreeOnTerminate ist True.

Wenn FreeOnTerminate = true ist, dann gibt sich der Thread beim Beenden selbst frei und der Eintrag in der Liste zeigt auf diese eventuell gerade freigegebene Instanz- Das ist böse!

Besser FreeOnTerminate auf false und dafür OwnsObjects auf true. Dann bleiben die Instanzen der Threads auch nach dem Beenden gültig und werden erst mit der Freigabe der Liste auch freigegeben.

Captnemo 23. Jun 2014 14:32

AW: Arbeiten mit TThreadList
 
Danke, FreeOnTerminate hab ich auf False gesetzt.

@Günther: Das werd ich mir auch noch mal genau anschauen.

Aber das mit WaitForSingleObject hab ich noch nicht verstanden. Rückgabewert hab ich in OH gefunden.
Aber mit dem Satz "The state of the specified object is signaled" ist mir noch nicht ganz klar. Heißt das jetzt, WaitForSingleObject wartet auf irgendeine Reaktion vom Object?

pertzschc 23. Jun 2014 14:48

AW: Arbeiten mit TThreadList
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1263256)
Ich habe das mal versucht in das Beispiel zu packen

Mit welchem Delphi läuft Dein Code? Bei mir im Delphi 2010 geht z.B. das TThread.CreateAnonymousThread nicht.

Danke für einen Hinweis,
Christoph

Uwe Raabe 23. Jun 2014 14:56

AW: Arbeiten mit TThreadList
 
Zitat:

Zitat von Captnemo (Beitrag 1263260)
Aber das mit WaitForSingleObject hab ich noch nicht verstanden. Rückgabewert hab ich in OH gefunden.
Aber mit dem Satz "The state of the specified object is signaled" ist mir noch nicht ganz klar. Heißt das jetzt, WaitForSingleObject wartet auf irgendeine Reaktion vom Object?

WaitForSingleObject wartet auf ein bestimmtes Ereignis. Welches das ist, hängt ganz vom Object (Event, Timer, Mutex) ab. Ein Thread löst das Signal beim Beenden aus.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:10 Uhr.
Seite 2 von 3     12 3      

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