Example of Thread Pool in Delphi

Asked

Viewed 2,460 times

2

How do I make a pool of Thread, I need to execute a process that contains several records, but I need to send on demand, send 10 and as you release, send more.... how can I do ?

I set an example...

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
   MinhaThread = class(TThread)
   procedure Execute; override;
   procedure Verifica;
   procedure Fechar;
   Private
   constructor Create();
end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    thread: MinhaThread;
  public
    { Public declarations }
    procedure consultaProcesso(Sender: TObject);
    procedure postJSON(JSON:String);
  end;

var
  Form1: TForm1;
  I : Integer;
  JSON:String;

implementation

{$R *.dfm}

{ MinhaThread }

constructor MinhaThread.Create;
begin
inherited
  Create(True);
  FreeOnTerminate := True;
  Priority := tpLower;
  Resume;
end;

procedure MinhaThread.Execute;
Var Sender : TObject;
begin
   Synchronize(Verifica);
   Form1.consultaProcesso(Sender); // Executar Rotina ( Procedures )

   while not Terminated do
    begin
        Sleep (10);
        Terminate; // Finaliza a Thread
        Synchronize(Fechar);
    end;

end;

procedure MinhaThread.Fechar;
begin
  //application.terminate;
end;

procedure MinhaThread.Verifica;
begin
  Form1.Caption := 'EXECUTANDO...'+IntToStr(I);
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  thread := MinhaThread.Create();
end;

procedure TForm1.consultaProcesso(Sender: TObject);
begin
  //exemplo com o for
  // porem aqui eu percorro a query, passo 
  // para a variavel JSON o json que está na query
  // e chamo o metodo post
  for I := 0 to 100 do
    begin
      postJSON(JSON);
    end;
end;

procedure TForm1.postJSON(JSON: String);
begin
  //faz um post pelo idHTTP;
  Memo1.Lines.Add(DateTimeToStr(now)+ ' - Executando JSON '+IntToStr(I));
  //para simular um tempo de espera do retorno
  Sleep(1000);
  //retorno...
  Memo1.Lines.Add(DateTimeToStr(now)+ ' - Retorno JSON '+IntToStr(I));
end;

end.

In the method consultaProcesso put a for, but it would be the same as the while that I do in the query catching the JSON and moving on to the way postJSON, in this method put a sleep to simulate a return time I have from post carried out by idHTTP.

  • Could you post what you already have? so it would be easier for us to help.

  • I have a query with about 10,000 records, what I do is go through it and do a post with idHttp; .... basically; while not qryRegistros.eof of Begin //monto json with the records //I call the post postJSON(JSON); qryRegistros.next; end;

  • Ok, if you limit the amount of records returned by your query, it does not solve the problem?

  • I guess not, since I have to generate everyone’s json and send it, then the plan would be to put it in a thread pool to go processing....

  • Right, but with each Thread run you want to run 10 Query records, correct?

  • would send 10 records to 10 threads, wait and as soon as you finish sending the next....

  • I get it, give me the code of this your query, so I use it myself to do the listing.

  • It’s simple, I have the field with json, so I just pass it in the post.... <code> with query.eof do Begin postJSON(query.Fieldbyname('JSON'). asString)); query.next; end; </code>

  • Which version of Delphi are you using?

  • use the Delphi Berlin

  • Since you are passing a very superficial structure, I will only be able to help you superficially too, within Form1 you have the thread variable, this variable would be the one I put in my code Minhasthreads: Array of Minhathread;. and your query should be within Form1 and for every 10 record you would create a new thread within the list, as I wrote in my reply below. Then just wait for all threads to finish running.

  • as the original code queries the bank and uses other classes, I made this functional example that approaches 100% of the process and problem I have, anyway I appreciate the attention and I will try here, thank you.

  • Take a look at http://www.omnithreadlibrary.com/index.htm. is a framework that does thread Poll and more! Download and look at the example 11_ThreadPool

Show 8 more comments

1 answer

2

See if this process helps solve your problem:

var
  MinhasThreads: Array of MinhaThread;
  i: Integer;
begin

  SetLength(MinhasThreads, 0);

  // Criando as threads dinâmicamente
  for i := 0 to 9 do
    begin
      SetLength(MinhasThreads, Length(MinhasThreads) + 1);
      MinhasThreads[High(MinhasThreads)] := MinhaThread.Create(True);
      MinhasThreads[High(MinhasThreads)].FreeOnTerminate := True;
      MinhasThreads[High(MinhasThreads)].Start;
    end;

  // Verificar se existe alguma Thread em execução
  //O sistema irá ficar rodando esse laço de repetição até que todas as threads sejam finalizadas.
  i := 0;
  while (i <= High(MinhasThreads)) do
    begin
      if (MinhasThreads[i] <> nil) then
        i := 0
      else
        Inc(i);
    end;
end;

The idea is, create all threads within an array, these threads are set to self-destruct as soon as the procedure execute is finalized.

  • Could you explain some excerpts of the code, because in Setlength.. what is your function ? o for will be the while of my records ?

  • Setlength is responsible for setting the size of the array, that is, how many positions it will have. The for would rather be its while, and with each loop the Setlength function adds a position in the array. So we can have an indeterminate amount of threads running.

  • ok, and where I will set the execution method, today I use the thread this way .... ``

  • Your procedure will be triggered on this line: Minhasthreads[High(Minhasthreads)]. Start; In Thread Create we pass True, that is, it will be created but not executed. So it will only run when we give Start.

  • ok, and where I will set the execution method, today I use the thread that way .... ....&#xA;procedure MinhaThread.Execute;&#xA;Var Sender : TObject;&#xA;begin&#xA; synchronize(Verifica);&#xA; frmProcessos.consultaProcesso(Sender); &#xA;&#xA; while not Terminated do&#xA; begin&#xA; Sleep (10);&#xA; Terminate; // Finaliza a Thread&#xA; synchronize(Fechar);&#xA; end;&#xA;&#xA;end;&#xA; Today uses the Thread...the query Process is query I go through, I did not identify how I would send 10, wait for the return and send as soon as it is releasing....

  • This example you passed this very superficial, so it edits your question and puts there all the code of your thread, and the code from where you call the thread.

  • Okay, I’ve put together an example of how I’m doing, I think now it’s easier to understand my suffering.

  • Did you understand the example I set ? I really need to adapt this process, because 18,000 records were more than 18 hours running in the current method.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.