![]() |
Wie Threads beenden und freigeben?
Ich habe eine eigene Thread-Klasse erstellt: TMyThread. Wenn der Benutzer auf einen Button klickt, wird eine Instanz dieser Klasse erzeugt und gestartet. Der Benutzer kann und soll das beliebig oft und schnell tuen können.
Immer wenn einen neue Instanz erzeugt/gestartet wird, sollen alle anderen Threads beendet und *freigegeben* werden. Die neue Instanz soll sofort gestartet werden, egal was die anderen Threads noch machen, das das Beenden zeitintensiv sein kann. Beim Beenden des Programms sollen alle noch laufenden Thread beendet werden und das Programm erst schließen, wenn alle Thread fertig sind. Ich habe dazu folgende Lösung. Problem dabei ist, das freigeben der laufenden Threads. Wenn ich das mit MyThread.FreeOnTerminate := true machen lasse, gibt's beim Programmende in TerminateAll() die Meldung "Thread-Fehler: Das Handle ist ungültig (X)' aufgetreten" Aber wie soll ohne FreeOnTerminate freigegeben werden? Problem 2: Am Ende von TMyThread.Execute soll ein TNotify-Event ausgelößt werden, wenn der *zuletzt* gestartet Thread fertig ist. Evtl. hängen diese beiden Fragestellungen ja zusammen. Danke für die Hilfe!
Delphi-Quellcode:
Edit: Leider kann ich den Titel dieser Frage nicht ändern. Kann das mal bitte ein Admin erledigen? Z.B. in "Wie Threads beenden und freigeben?"
type
TMyThread = class(TThread) private public procedure Execute; override; end; TMyThreadList = class(TThreadList<TMyThread>) private public procedure TerminateAll; procedure AddAndStartThread(NewThread: TMyThread); end; TForm1 = class(TForm) btn1: TButton; procedure FormCreate(Sender: TObject); procedure btn1Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private procedure EvTerminate(Sender: TObject); public MyThreadList: TMyThreadList; end; var Form1: TForm1; implementation {$R *.dfm} procedure TMyThreadList.AddAndStartThread(NewThread: TMyThread); var i: Integer; Items: TList<TMyThread>; begin Items := LockList; try Items.Insert(0, NewThread); for i := Items.Count - 1 downto 1 do TMyThread(Items[i]).Terminate; NewThread.Start; finally UnlockList; end; end; procedure TMyThreadList.TerminateAll; var i: Integer; Items: TList<TMyThread>; begin Items := LockList; try for i := Items.Count - 1 downto 0 do begin TMyThread(Items[i]).Terminate; TMyThread(Items[i]).WaitFor; end; finally UnlockList; end; end; procedure TForm1.btn1Click(Sender: TObject); var MyThread: TMyThread; begin MyThread := TMyThread.Create(true); MyThread.FreeOnTerminate := false; MyThread.OnTerminate := EvTerminate; MyThreadList.AddAndStartThread(MyThread); end; procedure TForm1.EvTerminate(Sender: TObject); begin MyThreadList.Remove(Sender as TMyThread); end; procedure TForm1.FormCreate(Sender: TObject); begin MyThreadList := TMyThreadList.Create; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin MyThreadList.TerminateAll; end; { TMyThread } procedure TMyThread.Execute; var tc: Cardinal; a: Int64; begin if not Terminated then begin //Das nur als Beispiel für Arbeit, die der Thread macht. while GetTickCount - tc > 10000 do begin if Terminated then break; inc(a); end; //Event hier, wenn das der letzte gestartete Thread ist. end; end; end. |
AW: Thread
Zitat:
Delphi-Quellcode:
nichts für diesen Fall. Wenn ein Thread FreeOnTerminate hast solltest du nach dem Starten die Referenz nie wieder anfassen. Ab dann ist nicht mehr definiert ob die Thread-Instanz bereits freigegeben worden ist oder nicht.
FreeOnTerminate
Zitat:
Delphi-Quellcode:
doch schon genau die richtige Stelle dafür! Entferne es nach wie vor aus deiner Liste und danach gibst du den TThread frei.
EvTerminate
Zu Problem 2 würde ich deinem Thread die Logik dafür nicht mitgeben. Das
Delphi-Quellcode:
ist doch auch hier eigentlich die perfekte Gelegenheit dafür!
EvTerminate
|
AW: Thread
Zitat:
Zitat:
|
AW: Thread
Du könntest nach dem Starten eines Threads alle anderen Threads aus der Threadliste löschen.
|
AW: Thread
Zitat:
|
AW: Thread
.. Du könntest das onTerminate Ereignis verwenden.
Damit könnte der Thread eine Nachricht absetzen wenn er beendet wird. Die Nachricht könnte dein Haptprogramm veranlassen den Thread aus der Liste zu entfernen. Edit. Das machst Du doch schon - wo ist dann das Problem? Grüße Klaus |
AW: Thread
Zitat:
Zitat:
|
AW: Thread
Zitat:
Zitat:
|
AW: Thread
Zitat:
|
AW: Thread
Threads haben zusätzlich zur Terminated noch die Finished Property. Die könntest Du abfragen, und jeden Thread, der Finished ist freigeben. Denn Terminated gibt eigentlich nur an, daß ein Thread den Terminate Befehl bekommen hat.
Und ein Thread.Free darfst Du beim entfernen aus der Liste auch machen. Sherlock |
AW: Thread
Zitat:
denn du löscht den Thread aus der Liste wenn er sich beendigt hat. Wie der Name schon sagt FreeOnTerminate wird der Thread freigegeben wenn er beendet ist. Da musst Du nichts mehr freigeben. Grüße Klaus |
AW: Thread
Zitat:
|
AW: Thread
Liste der Anhänge anzeigen (Anzahl: 1)
Threads immer mit FreeOnTerminate = TRUE, damit hat man in Summe den geringsten Stress. Wenn das Ende des Threads von Bedeutung ist, einfach das OnTerminate - Event benutzen.
Das Warten beim Programmende kann man zwar machen, besser ist es ihmo den Thread so zu bauen, das er in Frieden sterben darf. Die kleine Demo zeigt das Ende an und wartet (aber schön ist anders 8-)) |
AW: Thread
Ohne in dein Beispiel zu schauen, aber grade
Delphi-Quellcode:
und dann das Hauptformular zumachen ist gerade nicht in Frieden sterben lassen. Das ist eher von hinten anschleichen und in den Kopf schießen. :duck:
FreeOnTerminate = True
Oder meintest du dass man den Thread eher so bauen sollte dass er jederzeit einfach hart ausgeknipst werden darf? |
AW: Thread
Ist es eine Totsünde im FormCloseQuery bei CanClose True eine globale Variable auf TRUE zu setzen, welche der arbeitende Thread dann abfragt, seine Arbeit beendet und "sich in Frieden beendet"?
So würde ich es machen. Klar, man kann auch auf Terminated prüfen. Aber ich persönlich würde es mit einer eigenen Variable machen und den Thread an sich gar nicht erst anfassen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:46 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