Échantillon De Fil Simple Delphi

je suis nouveau avec ce truc de Threading à Delphi. donc, j'essaie de faire une simple application de requête qui fait un peu appel à la base de données et prend un peu de temps, donc je veux alerter l'utilisateur qu'il y a un processus de fond et doit être patient.

j'ai essayé beaucoup d'échantillons, mais aucun d'eux ne fonctionne pour moi, S'il Vous Plaît, quelqu'un pourrait me montrer un échantillon simple qui pourrait fonctionner?

je sais que je dois déclarer un Type de TThread, avec Create et Override Execute... etc.. mais depuis que je suis perdu...

en utilisant Delphi 7, SQL Server 2005 et ADO, Windows XP sp3.-

Merci.

24
demandé sur Jose M. Vilomar 2010-08-10 20:22:35

2 réponses

Vous pouvez trouver de nombreux exemples sur le web de fils. La seule particularité, si vous utilisez des connexions ADO à l'intérieur du Thread, est que vous ne pouvez pas partager la même connexion.

Chaque thread doit créer sa propre connexion, sinon ils sont égaux (doit suivre les mêmes règles que n'importe quel autre thread.)

Un exemple que j'ai utilisé est:

  TADOSQLThread = class(TThread)
  private
    FADOQ: TADOQuery;  // Internal query
    FSQL: string;      // SQL To execute
    FID: integer;      // Internal ID

  public
    constructor Create(CreateSuspended:Boolean; AConnString:String;
                       ASQL:string; IDThread:integer);
    destructor Destroy; override;
    procedure Execute(); override;

    property ID:integer read FID write FID;
    property SQL:string read FSQL write FSQL;
    property ADOQ:TADOQuery read FADOQ write FADOQ;
  end;

le constructeur Create est dépassé, et ressemble à ceci:

constructor TADOSQLThread.Create(CreateSuspended:Boolean; AConnString:String;
                                 ASQL:string; IDThread:integer);
begin

  inherited Create(CreateSuspended);

  // ini
  Self.FreeOnTerminate := False;

  // Create the Query
  FADOQ := TAdoquery.Create(nil);
  // assign connections
  FADOQ.ConnectionString := AConnString;
  FADOQ.SQL.Add(ASQL);
  Self.FID := IDThread;
  Self.FSQL:= ASQL;
end;

Et la méthode execute est très simple:

procedure TADOSQLThread.Execute();
begin

  inherited;

  try
    // Ejecutar la consulta
    Self.FADOQ.Open;
  except
    // Error al ejecutar
    ...Error treattement
  end;
end;

pour démarrer et créer un thread, vous pouvez utiliser un code similaire à celui-ci:

  //crear el Thread
  th := TADOSQLThread.Create(True, mmConnection.Lines.Text, ASQL, AId);
  // internal for me (for controled the number of active threads and limete it)
  inc(numThreads);
  // evento finalizacion
  th.OnTerminate := TerminateThread;
  // Ejecutarlo
  th.Resume;

j'ai créé un TerminateThread méthode qui reçoit le contrôle des fils quand ils finissent. La seule différence avec les autres threads est le problème de connexion. Vous devez créer une nouvelle connexion sur chaque fil, il ne peut pas partager les mêmes ADOConnections avec les autres.

J'espère que cet exemple sera utile pour vous.

Cordialement

30
répondu Germán Estévez -Neftalí- 2015-07-05 09:26:13

Yup, vous déclarez un nouveau type qui hérite de TThread:

TMyWorkerThread = class(TThread)
end;

ensuite, vous ajoutez une fonction override pour Execute ():

TMyWorkerThread = class(TThread)
public
  procedure Execute; override;
end;

Cette procédure sera appelée lorsque vous démarrez votre fil. Il sera exécuté en parallèle avec votre programme principal. Nous allons l'écrire.

procedure TMyWorkerThread.Execute;
begin
  //Here we do work
   DoSomeWork();
   DoMoreWork();
  //When we exit the procedure, the thread ends.
  //So we don't exit until we're done.
end;

Comment l'utiliser? Disons que vous voulez commencer à travailler lorsque l'utilisateur clique sur le bouton. Vous écrivez un handler OnClick:

procedure TMainForm.Button1Click(Sender: TObject);
begin
  TMyWorkerThread.Create(false);
end;

C'est ça. Après que l'utilisateur cliquez sur le bouton, votre fil commence et continue à faire ce que vous avez écrit dans Execute. Si l'utilisateur clique à nouveau sur le bouton, un autre thread démarre, puis un autre - un à chaque clic. Ils s'exécuteront tous en parallèle, chacun faisant tout ce qui est écrit dans Execute() et ensuite se terminant.

disons que vous voulez vérifier si le travail est terminé. Pour cela, vous devrez stocker la référence à votre fil quelque part:

TMainForm = class(TForm)
{...skipped...}
public
  MyWorkerThread: TThread;
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  //This time we make sure only one thread can be started.
  //If one thread have been started already, we don't start another.
  if MyWorkerThread<>nil then
    raise Exception.Create('One thread have already been started!');
  MyWorkerThread := TMyWorkerThread.Create(false);
end;

procedure TMainForm.Button2Click(Sender: TObject);
begin
  //If the work is not over yet, we display message informing the user we're still working
  if (MyWorkerThread<>nil) and (WaitForSingleObject(MyWorkerThread.Handle, 0)<>WAIT_OBJECT_0) then
    MessageBox(Self.Handle, pchar("The work is not yet done!"), pchar("Still running"), MB_OK);
end;

Comme vous le voyez, nous vérifions si un thread est toujours en cours d'exécution en appelant une fonction Windows appelée WaitForSingleObject. Cette fonction attend que le thread fonctionne, ou que le timeout soit écoulé, et comme nous spécifions le timeout de 0, elle existe juste immédiatement si le thread n'est pas encore terminé.

49
répondu himself 2010-08-11 06:56:51