multithreading 简单线程示例 Delphi
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3451138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple Thread Sample Delphi
提问by Jose M. Vilomar
I am new with this stuff of Threading in Delphi. so, I am trying to make a simple query aplication that make a bit call up for the database and take a bit of time, so I want to alert the user that there is a background process and have to be patient.
我是 Delphi 中线程的新手。所以,我正在尝试制作一个简单的查询应用程序,它会调用数据库并花费一些时间,所以我想提醒用户有一个后台进程并且必须耐心等待。
I tried many samples, but none of them work for me, Please, could somebody show me a simple sample that could work?
我尝试了很多样本,但没有一个对我有用,请问有人可以给我看一个可以工作的简单样本吗?
I know that I have to Declare a Type of TThread, with Create and Override Execute... etc.. but since that I am lost...
我知道我必须声明一种类型的 TThread,使用创建和覆盖执行......等等......但是因为我迷路了......
Using Delphi 7, SQL Server 2005 and ADO, Windows XP sp3.-
使用 Delphi 7、SQL Server 2005 和 ADO、Windows XP sp3.-
Thanks.
谢谢。
回答by himself
Yup, you declare a new type which inherits from TThread:
是的,您声明了一个继承自 TThread 的新类型:
TMyWorkerThread = class(TThread)
end;
Then you add a function override for Execute():
然后为 Execute() 添加一个函数覆盖:
TMyWorkerThread = class(TThread)
public
procedure Execute; override;
end;
That procedure will be called when you start your thread. It will be executed in parallel with your main program. Let's write it.
当您启动线程时将调用该过程。它将与您的主程序并行执行。我们来写吧。
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;
How to use this? Let's say you want to start doing work when the user clicks button. You write an OnClick handler:
这个怎么用?假设您想在用户单击按钮时开始工作。您编写一个 OnClick 处理程序:
procedure TMainForm.Button1Click(Sender: TObject);
begin
TMyWorkerThread.Create(false);
end;
That's it. After the user clicks button, your thread starts and proceeds with doing whatever it is that you wrote in Execute. If the user clicks the button again, another thread will start, and then another - one every click. They will all run in parallel, each doing all what's written in Execute() and then ending.
就是这样。用户单击按钮后,您的线程将启动并继续执行您在 Execute 中编写的任何内容。如果用户再次单击该按钮,将启动另一个线程,然后另一个线程 - 每次单击一个。它们都将并行运行,每个都执行 Execute() 中编写的所有内容,然后结束。
Let's say you want to check if the work is over. For that, you'll have to store the reference to your thread somewhere:
假设您想检查工作是否结束。为此,您必须在某处存储对线程的引用:
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;
As you see, we're checking if a thread is still running by calling a Windows function called WaitForSingleObject. This function waits until the thread is done working, or the timeout is elapsed, and as we specify the timeout of 0, it just exists immediately if the thread is not over yet.
如您所见,我们通过调用名为 WaitForSingleObject 的 Windows 函数来检查线程是否仍在运行。这个函数一直等到线程完成工作,或者超时时间过去,因为我们指定超时时间为 0,如果线程还没有结束,它就会立即存在。
回答by Germán Estévez -Neftalí-
You can find many examples on the web of threads. The only special feature, if you are using ADO connections inside the Thread, is that you can't share the same connection.
Each thread must create its own connection, otherwise they are equal (should follow the same rules as any other thread.)
您可以在线程网络上找到许多示例。如果您在 Thread 内使用 ADO 连接,唯一的特殊功能是您不能共享相同的连接。
每个线程必须创建自己的 connection,否则它们是相等的(应遵循与任何其他线程相同的规则。)
An sample that I have used is this:
我使用过的一个示例是这样的:
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;
The Create constructor is overrided, and look like this:
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;
And the execute method is very simple:
而execute方法非常简单:
procedure TADOSQLThread.Execute();
begin
inherited;
try
// Ejecutar la consulta
Self.FADOQ.Open;
except
// Error al ejecutar
...Error treattement
end;
end;
To start and create a thread you can use code similar to this:
要启动和创建线程,您可以使用类似于以下的代码:
//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;
I have create a TerminateThreadmethod that receive the control of threads when they finish. The only different to other threads is the connection problem. You must create a new connection on every thread, It can't share the same ADOConnections with others.
I hope this example will be useful for you.
我创建了一个TerminateThread方法,该方法在线程完成时接收线程的控制权。与其他线程唯一不同的是连接问题。您必须在每个线程上创建一个新连接,它不能与其他人共享相同的 ADOConnections。
我希望这个例子对你有用。
Regards
问候