Newsgroup: it.comp.lang.delphi
Titolo: Conteggio multi-thread

Ciao a tutti,
  uso D7 e in una applicazione uso i multi-thread per fare degli
accessi ad internet. FIno qui tutto bene, io mio problema è che non
riesco a contare o limitare il numero di thread lanciati.
Mi speigo meglio, vorrei evitare che vengano lanciati
contemporaneamente più di X thread. Cioè una volta che il programma si
rendesse conto che stanno girando X thread dovrebbe attendere che ne
finisca uno prima di lanciare il successivo.
Avete idee o esperienze in merito?
Grazie a tutti

Grazie a tutti
Fai incrementare una variabile (esterna al thread) quando il thread
parte e falla decrementare quando si chiude.
Devi gestire l'accesso al contatore serializzandolo (cerca nei post se
ne parla spesso).
Per fare questo il thread deve avere il riferimento al contatore, lo
puoi passare nella "Create" in modo da usarlo quando il lavoro (metodo
"execute") č finito.
Ciao

Avete idee o esperienze in merito?
- Dichiara un array di X thread;
- Alloca ciascuno dei thread e fa' sì che ciascuno di essi memorizzi
internamente l'indice associato nell'array;
- Quando un thread termina, fa' sì che comunichi al thread principale
la sua fine e che gli passi il suo indice;
- A quel punto, il thread principale alloca un nuovo thread al suo
posto;
Piccolo esempio:
unit WorkerThread;
interface
uses
  Windows, Messages, Classes;
const
  CM_SEND_COUNT = WM_USER+100;
  CM_SEND_PROGRESS = WM_USER+101;
  CM_THREAD_TERMINATE = WM_USER+102;
  CM_THREAD_TERMINATED = WM_USER+103;
type
  TWorkerThread = class(TThread)
  private
    FCreatorId: Integer;
    FWindowHandle: HWND;
  protected
    procedure Execute; override;
  public
    constructor Create(ACreatorId: Integer; AWindowHandle: HWND);
  end;
implementation
{ TWorkerThread }
constructor TWorkerThread.Create(ACreatorId: Integer; AWindowHandle:
HWND);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FCreatorId := ACreatorId;
  FWindowHandle := AWindowHandle;
end;
procedure TWorkerThread.Execute;
var
  Count: Integer;
  lpMsg: tagMsg;
begin
  Count := Random(30)+5;
  PostMessage(FWindowHandle, CM_SEND_COUNT, FCreatorId, Count);
  while (not Terminated) and (Count>0) do begin
    if PeekMessage(lpMsg, 0, 0, 0, PM_REMOVE) then begin
      if lpMsg.message = CM_THREAD_TERMINATE then begin
        Terminate;
      end;
    end;
    Sleep(400);
    Dec(Count);
    PostMessage(FWindowHandle, CM_SEND_PROGRESS, FCreatorId, Count);
  end;
  PostMessage(FWindowHandle, CM_THREAD_TERMINATED, FCreatorId, 0);  
end;
end.
E poi la unit principale:
unit frm_main;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
  Dialogs, WorkerThread, StdCtrls, ComCtrls, AppEvnts;
type
  TThreadInfo = class
  public
    ThreadLabel: TLabel;
    ThreadBar: TProgressBar;
    Thread: TThread;
  end;
  TForm1 = class(TForm)
    Button1: TButton;
    ApplicationEvents1: TApplicationEvents;
    procedure Button1Click(Sender: TObject);
    procedure ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
  private
    FThreadInfoArray: array of TThreadInfo;
  public
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
  I, X: Integer;
begin
  Button1.Enabled := False;
  Randomize;
  X := Random(10)+3;
  SetLength(FThreadInfoArray, X);
  for I := Low(FThreadInfoArray) to High(FThreadInfoArray) do
  begin
    FThreadInfoArray[I] := TThreadInfo.Create;
    with FThreadInfoArray[I] do begin
      ThreadLabel := TLabel.Create(Self);
      ThreadLabel.Parent := Self;
      ThreadLabel.Left := 8;
      ThreadLabel.Top := 24*I+8;
      //
      ThreadBar := TProgressBar.Create(Self);
      ThreadBar.Parent := Self;
      ThreadBar.Left := 100;
      ThreadBar.Top := ThreadLabel.Top;
      ThreadBar.Smooth := True;
      //
      Thread := TWorkerThread.Create(I, Handle);
      ThreadLabel.Caption := Format('TID: %.8x', [Thread.ThreadID]);
      Thread.Resume;
    end;
  end;
end;
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
var
  Index: Integer;
begin
  case Msg.message of
    CM_SEND_COUNT: begin
      Index := Msg.wParam;
      FThreadInfoArray[Index].ThreadBar.Max := Msg.lParam;
      FThreadInfoArray[Index].ThreadBar.Position := Msg.lParam;
      Handled := True;
    end;
    CM_SEND_PROGRESS: begin
      Index := Msg.wParam;
      FThreadInfoArray[Index].ThreadBar.Position := Msg.lParam;
      Handled := True;
    end;
    CM_THREAD_TERMINATED: begin
      Index := Msg.wParam;
      with FThreadInfoArray[Index] do begin
        Thread := TWorkerThread.Create(Index, Handle);
        ThreadLabel.Caption := Format('TID: %.8x', [Thread.ThreadID]);
        Thread.Resume;
      end;
      Handled := True;
    end;
  end;
end;
end.