如何编写和执行一个线程

时间:2010-09-27 06:26:52

标签: multithreading delphi

我之前从未使用过线程,现在我正在尝试创建一个带有查询的线程来检查数据库状态。查询如下:

select (*) as DBCount from v$datafile where status in 'OFFLINE';

此查询返回脱机的所有数据库的总数。现在我想在Delphi中创建一个线程,当我运行它并在标签上显示结果时,它将在我的应用程序的后台执行此查询。

4 个答案:

答案 0 :(得分:7)

多线程很难。使用像AsyncCalls这样的简单线程框架可能会更好。

以下StackOverlow线程可能会为您提供有关如何解决问题的更多信息:

Delphi - Threading frameworks

How Do I Choose Between the Various Ways to do Threading in Delphi?

Delphi thread that waits for data, processes it, then resumes waiting

答案 1 :(得分:1)

使用AsyncCalls这很容易。让我们假设您的非线程代码看起来像这样(忽略所有错误处理):

Query := 'select (*) as DBCount from...';
ExecuteSQL(SqlConnection,Query);
SqlResult := GetSqlResult(SqlConnection);
SqlRow := GetSqlRow(SqlResult);
MyLabel.Text := SqlRow[0];
...Go on to do other things...

第二行阻塞(等待服务器回复)。您的新代码如下所示:

uses AsyncCalls;      //added to your existing uses statement
...
procedure DoesSomething();
var  Thread: TAsyncCall;                //your interface to AsyncCalls
  procedure AsyncSqlCall();             //this is a LOCAL procedure
    Query := 'select (*) as DBCount from...';
    ExecuteSQL(SqlConnection,Query);
    SqlResult := GetSqlResult(SqlConnection);
    SqlRow := GetSqlRow(SqlResult);
    EnterMainThread;
    try
      Assert(GetCurrentThreadId = MainThreadId);
      MyLabel.Text := SqlRow[0];
    finally
      LeaveMainThread;        
    end;

begin                           //this begins proc DoSomething()
  ...
  Thread := LocalAsyncCall(@AsyncSqlCall);
  ...Go on to do other things...
end;

我们所做的就是将阻塞的SQL调用放在本地proc中,并告诉AsyncCalls在另一个线程中执行它,同时主线程继续执行。唯一棘手的部分是使用VCL,这不是线程安全的。所以我在主线程中安全地运行了该行。

如果在某些时候您需要确保Async线程已经完成,您将执行此行来阻止主线程,直到AsyncSqlCall终止:

Thread.sync; 

这里非常好的事情是AsyncCalls处理有关创建线程池,创建线程等的所有内容。虽然在此示例中未显示,但您可以将变量传递给线程,并返回值。您不必使用本地proc,但这样做可以访问所有本地变量。您可以将所有这些全局化,然后在一个例程中启动Async线程,并在另一个例程中测试它的完成情况。

限制:

您的异步线程不得触摸(读取或写入)除自身变量之外的任何内容,并且在异步线程运行时,主线程不得触摸它们。你必须这样编码。没有什么能阻止你制造完全混乱。在上面的示例中,您的主线程不得触及Query,SqlConnection,SqlResult和SqlRow。如果您的代码的任何部分在Thread.sync调用之前使用了其中一个变量,那么您的代码将起作用 - 但是在您从未预料到的奇怪位置抛出异常。所以保持简单。

您的异步线程不得使用VCL。上面的示例显示了安全解决此限制的几种方法之一。

最后:

AsyncCalls不是一个完整的多线程框架。这只是一种调用procs& amp;异步运行(即无需等待)。不要试图把它推得太远 - 我的意思是,不要试图把它作为完全多任务程序的基础。

答案 2 :(得分:0)

在Delphi中有TThread类。您可以使用Delphi IDE中的简单向导(Turbo Delphi:File-> New-> Delphi Projects-> Delphi Files-> Thread Obcjet)创建这样的线程。在它的构造函数中创建与数据库的连接,在Execute方法中,您可以创建查询数据库的循环,更新一些全局变量(未声明为threadvar)并休眠一段时间。

答案 3 :(得分:0)

在这里,您可以找到有关在DataBase上使用线程的讨论。

Simple Thread Sample Delphi

有些代码对您有用。

问候。