Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Anzahl der Threads???


ralfi - Mi 26.11.03 11:18
Titel: Anzahl der Threads???
Hallo!

In meinem Programm habe ich einige Threads, jeder von dennen separat erstellt wurde (also kein Array of Threads oder so was). Jeder Thread macht irgendwas anderes.

1. Wie kann ich zu jedem Moment sehen, wieviele Threads z. Z. aktiv sind?

2. Wie kann ich es so synchronisieren, dass z. B. nicht mehr als 5 Threads glecihzeitig laufen dürfen und alle andere warten?

Danke! :-)


AndyB - Mi 26.11.03 11:23

Vor dem Erstellen eines neuen Threads erhöhst du eine Variable "AktiveThreads" um 1 und im Thread destruktor Destroy ziehst du wieder 1 ab. Somit steht in AktiveThread die Anzahl der gerade laufenden Threads (vorausgesetzt deine Threads beenden sich nachdem Execute beendet ist und warten nicht in Execute auf eine neue Aufgabe). Ansonsten wird es etwas komplizierter, da du den Zugriff auf "AktiveThreads" mit CriticalSections regeln müsstest.


ralfi - Mi 26.11.03 13:40

In allen Threads werden die Aufgaben wiederholt, solange Terminated=false.


Quelltext
1:
2:
while not terminated do
DoWork


Was muss ich in diesem Fall?


maxk - Fr 28.11.03 16:00


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
uses tlhelp32;

function GetThreadCount:integer;
var pe32:TProcessEntry32;
    Pid,Hnd:Cardinal;
begin
 Result:=0;
 Hnd:=CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS,0);
 if Hnd=INVALID_HANDLE_VALUE then exit;
 try
  GetWindowThreadProcessID(Application.Handle,@Pid);

  pe32.dwSize:=SizeOf(ProcessEntry32);
  if Process32First(Hnd,pe32)=true then repeat
   if Pid=pe32.th32ProcessID then begin
    Result:=pe32.cntThreads-1// Thread - MainThread (Application)
    exit;
   end;
  until not Process32Next(Hnd,pe32);
 finally
  CloseHandle(Hnd);
 end;
end;
Funktioniert wunderbar.


Delete - Fr 28.11.03 17:04

Was soll das exit in der if-Bedingung? So wird dein Handle nie geschlossen. Und warum cntThreads-1? Hast du gar keinen eigenen Thread erstellt, liefert dir das 0 und das stimmt nicht, der Hauptthread ist ja auch noch da. Und wozu die Schleife? Übergibst du bei CreateToolHelp32Snapshot als zweiten Parameter 0, hast du schon einen Hanlde auf deinen eigenen Prozess.

So würde es bei mir aussehen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
uses tlhelp32;

function GetThreadCount(Handle: THandle): integer;
var
  pe32: TProcessEntry32;
  SnapShot: THandle;
  NumThreads: Cardinal;
begin
  NumThreads := 0;
  SnapShot := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);  // 0: current process
  if SnapShot <> INVALID_HANDLE_VALUE then
  try
    pe32.dwSize := SizeOf(ProcessEntry32);
    if Process32First(SnapShot, pe32) then
      NumThreads := pe32.cntThreads;
  finally
    CloseHandle(SnapShot);
  end;
  result := NumThreads;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(GetThreadCount(Handle)));
end;


AndyB - Sa 29.11.03 14:32

Luckie hat folgendes geschrieben:
if Process32First(SnapShot, pe32) = true then

Und viel Spaß mit Delphi < 5.

Man sollte nicht auf True testen, sondern einfach

Delphi-Quelltext
1:
if Process32First(SnapShot, pe32) then                    

schreiben, dann wird auf <> 0 getestet, was bei WinAPI Funktionen besser ist.


Delete - Sa 29.11.03 15:14

Führt das bei Delphi < 5 echt zu Problemen? Uiuiuiui, gleich mal verbesseren. danke für den Hinweis, ist noch vom Copy and paste übriggeblieben. :wink:


maxk - Sa 29.11.03 17:38

Luckie hat folgendes geschrieben:
Was soll das exit in der if-Bedingung? So wird dein Handle nie geschlossen. Und warum cntThreads-1?
Durch das exit springt Delphi automatisch zum finally-Block, wo das Handle geschlossen wird! cntThreads-1, weil ja hier nur das vorkommen von selbsterstellten TThreads in Erfahrung gebracht werden muss. Wobei dein Code natürlich trotzdem besser ist :roll:


Delete - Sa 29.11.03 17:48

Falsch. Ein exit verlässt die ganze Prozedur. Mit einem break kommst du aus der Schleife raus! Aber die Schleife ist immer noch Blödsinn.
Zitat:

weil ja hier nur das vorkommen von selbsterstellten TThreads in Erfahrung gebracht werden muss

Ja, aber dann würde ich die Anzahl der Threads nachher abziehen. Denn so ist die Funktion universell einsetztbar und die Wiederverwendbarkeit höher.


maxk - Sa 29.11.03 18:05

Delphi Hilfe hat folgendes geschrieben:
Note: Exit passes control away from the current procedure, not merely the current block. But Exit does not violate the flow of control dictated by a try..finally construct; if Exit is called inside the try clause, the finally clause is still executed.


AndyB - Sa 29.11.03 18:06

Luckie hat folgendes geschrieben:
Falsch.

Das Exit geht alle finally-Blöcke (der höheren Ebenen) durch. Man muss dort nur einen Breakpoint setzen und schon bleibt der Debugger im finally-Teil stehen.


Delete - Sa 29.11.03 18:14

Oh. Wieder was gelernt. :P