![]() |
THREADS: Anzahl der gerade aktiven Threads
Hallo,
ich erzeuge in Abhängigkeit der Anzahl der Einträge einer ListBox Treads der selben Klasse:
Delphi-Quellcode:
Da diese Printjobs unterschiedlich lange dauern, möchte ich wissen wieviele Threads gerade aktiv sind, da ich max. 16 Threads zugleich zulassen möchte.
BEGIN
FOR i := 0 TO ListBox1.Items.Count - 1 DO BEGIN ... TFlappPrintThread.Create(ListBox1.Items.Strings[i], i, ListBox1); END; END; Gibt es die Möglichkeit die Anzahl aktiven Threads abzufragen, oder muß ich mir selbst eine Art Stack basteln? p.s. Die Threads werden nach Beendigung sofort zerstört, so wie es mir ![]() |
Zähl doch einfach mit einer globalen Variable mit. Beim Erstellen erhöhen und beim Beenden erniedrigen.
|
Ergänzung: das Erhöhen und Erniedrigen muss aber atomar durchgeführt werden! Schau dir dazu die Interlock*-Funktionen an...
|
Danke @Motzi und @Luckie,
aber ich komme mit den Threads und Eueren Tips nicht klar :cry: (bin noch Thread-Anfänger) Ich übergebe iNumberOfThreads beim 1. Aufruf in meiner Form1-Unit mit:
Delphi-Quellcode:
in meiner Thread-Unit mache ich dann das:
iNumberOfThreads := 0;
FOR i := 0 TO ListBox1.Items.Count - 1 DO //Maximal 16 THREADS zugleich!!! BEGIN ... TFlappPrintThread.Create(sFile, i, ListBox1, iNumberOfThreads); ... END; ... WHILE CloseIt DO BEGIN Application.ProcessMessages; Label1.Caption := IntToStr(iNumberOfThreads); // HIER SOLLTE DIE ANZAHL DER OFFENEN THREADS STEHEN -ist aber immer Null :-(( Application.ProcessMessages; Form1.Refresh; Application.ProcessMessages; END;
Delphi-Quellcode:
CONSTRUCTOR TFlappPrintThread.Create(CONST aFile: STRING; CONST aThreadID: Integer; aListBox: TListBox; iNumberOfThreads: Integer);
BEGIN FaListbox := aListBox; FaThreadID := aThreadID; FiNumberOfThreads := iNumberOfThreads; FaFile := aFile; FreeOnTerminate := true; // Thread freigeben, wenn beendet INHERITED Create(false); // False = sofort starten END;
Delphi-Quellcode:
PROCEDURE TFlappPrintThread.Execute;
VAR ShExecInfo : TShellExecuteInfo; BEGIN InterlockedIncrement(FiNumberOfThreads); // INTERLOCK++ TRY IF NOT FileExists(FaFile) THEN BEGIN MessageDlg('File: ' + FaFile + ' not found', mtError, [mbOk], 0); END; FillChar(ShExecInfo, SizeOf(ShExecInfo), 0); WITH ShExecInfo DO BEGIN cbSize := SizeOf(ShExecInfo); fMask := SEE_MASK_NOCLOSEPROCESS; // SEE_MASK_NOCLOSEPROCESS OR SEE_MASK_FLAG_DDEWAIT; lpFile := PChar(FaFile); lpVerb := 'print'; nShow := SW_HIDE; //SW_SHOW; END; IF ShellExecuteEx(@ShExecInfo) THEN BEGIN WaitForSingleObject(ShExecInfo.hProcess, INFINITE); //0 Synchronize(SyncListbox); InterlockedDecrement(FiNumberOfThreads); // INTERLOCK-- END ELSE ShowMessage('Fehler beim Öffnen'); FINALLY Terminate; // dann beenden END; END; |
Hi,
ich hab schon mal gleiches Problem bearbeitet und folgenden Lösungsansatz gewählt. Mein Thread beinhaltet ein Property vom Typ TNitifyEvent. Beim Terminieren des Threads rufe ich dieses Ereignis auf und meine Hauptanwendung bekommt die entsprechende Mitteilung. Ob dann ein Counter oder etwas anderes bearbeitet wird bleibt Dir überlassen.
Delphi-Quellcode:
Wenn der Thread beendet wird rufe ich das Ereignis auf
type
TMapThread = class(TThread) private { Private-Deklarationen } FIsSetObj : Boolean; FIsSetCon : Boolean; FOnFinish : TNotifyEvent; protected procedure ExecuTMapte; override; public property IsSetObject : Boolean read FIsSetObj write FIsSetObj; property IsSetCon : Boolean read FIsSetCon write FIsSetCon; property OnFinish : TNotifyEvent read FOnFinish write FOnFinish;
Delphi-Quellcode:
In der Hauptanwendung wird nach dem Creieren des Thread die Ereignis-Procedure zugewiesen und in dieser entsprechend reagiert.
If Assigned(FOnFinish) then FOnFinish(self);
MyThread := TMapThread.Create(True); OnFinish := OnThreadFinish; TMain.OnThreadFinish(Sender : TObject); begin dec(mein_globaler_Threadcounter); end; [delphi] |
@oki,
Vielen Dank, es funktioniert!! :dancer: :dancer2: p.s. Eine kleine Frage noch (wie gesagt ich bin kein Thread-Profi): Ist dieser Code auch "Thread-Save", ich meine damit, was passiert in
Delphi-Quellcode:
wenn mehrere Threads zugleich dieses Ereignis anstoßen (Stichwort: Synchronize)?
TMain.OnThreadFinish(Sender : TObject);
|
Hi,
ich rufe das OnFinisch-Ereignis aus dem Thread in einer eigenen Thread-Methode auf. Dort werden noch andere Sachen bearbeitet. Diese Methode rufe ich aus Execute mit Syncronize auf. Bis dato habe ich mit den Ereignissen keine Probleme gehabt. Es benutzen bei mir auch alle Threads die gleiche Ereignisbehandlungsroutine des Main-Fensters. Ob es da aber Probleme geben kann bin ich mir nicht hundert prozentig sicher. Ich würde aber sagen, da die Ereignisbehandlung über die Botschaftsschlange von Windows läuft dürfte nichts passieren. Zusätzlich mache ich bei mir noch folgendes. Ich merke mir beim kreieren die Thread-Handle in einer Liste. Über den Parameter Sender bekomme ich heraus welcher Thread sich gerade beendet hat. Ich hoffe, das hat geholfen. Gruß oki |
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:14 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