简单的线程示例Delphi

Jos*_*mar 29 delphi multithreading

我是熟悉Delphi中线程的新手.所以,我试图制作一个简单的查询应用程序,为数据库调用一点并花一点时间,所以我想提醒用户有一个后台进程,必须耐心等待.

我尝试了很多样品,但它们都不适合我,拜托,有人能告诉我一个可以使用的简单样品吗?

我知道我必须声明一种类型的TThread,使用Create和Override Execute ......等等.但是因为我失去了...

使用Delphi 7,SQL Server 2005和ADO,Windows XP sp3.-

谢谢.

him*_*elf 53

是的,你声明一个从TThread继承的新类型:

TMyWorkerThread = class(TThread)
end;
Run Code Online (Sandbox Code Playgroud)

然后为Execute()添加函数覆盖:

TMyWorkerThread = class(TThread)
public
  procedure Execute; override;
end;
Run Code Online (Sandbox Code Playgroud)

启动线程时将调用该过程.它将与您的主程序并行执行.我们来写吧.

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;
Run Code Online (Sandbox Code Playgroud)

怎么用?假设您想在用户单击按钮时开始工作.你编写一个OnClick处理程序:

procedure TMainForm.Button1Click(Sender: TObject);
begin
  TMyWorkerThread.Create(false);
end;
Run Code Online (Sandbox Code Playgroud)

而已.用户单击按钮后,您的线程将启动并继续执行您在Execute中编写的任何内容.如果用户再次单击该按钮,则另一个线程将启动,然后是另一个 - 每次单击一个.它们都将并行运行,每个都执行在Execute()中写入的所有内容,然后结束.

假设您要检查工作是否结束.为此,您必须将引用存储在某处:

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;
Run Code Online (Sandbox Code Playgroud)

如您所见,我们通过调用名为WaitForSingleObject的Windows函数来检查线程是否仍在运行.此函数等待,直到线程完成工作,或超时已过,并且当我们指定超时为0时,如果线程尚未结束,它将立即存在.

  • 我知道这只是示例代码,但是注释说明如果用户多次单击按钮会发生什么会很有用. (2认同)

Ger*_*lí- 33

您可以在线程网上找到许多示例.如果您在线程内使用ADO连接,唯一的特殊功能是您不能共享相同的连接.
每个线程必须创建自己的连接,否则它们是相同的(应该遵循与任何其他线程相同的规则.)

我用过的样本是这样的:

  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;
Run Code Online (Sandbox Code Playgroud)

Create构造函数被覆盖,如下所示:

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;
Run Code Online (Sandbox Code Playgroud)

而execute方法非常简单:

procedure TADOSQLThread.Execute();
begin

  inherited;

  try
    // Ejecutar la consulta
    Self.FADOQ.Open;
  except
    // Error al ejecutar
    ...Error treattement
  end;
end;
Run Code Online (Sandbox Code Playgroud)

要启动并创建一个线程,您可以使用与此类似的代码:

  //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;
Run Code Online (Sandbox Code Playgroud)

我创建了一个TerminateThread方法,它在完成后接收线程控制.与其他线程唯一不同的是连接问题.您必须在每个线程上创建一个新连接,它不能与其他线程共享相同的ADOConnections.
我希望这个例子对你有用.

问候