精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● Delphi>>其他>>线程>>DELPHI下的多线程程序设计

主题:DELPHI下的多线程程序设计
发信人: teleme(PassWord)
整理人: teleme(2001-02-11 11:16:14), 站内信件

DELPHI下的多线程程序设计 
梁毅 李韬 
  我们知道,win95或winNT都是“多线程”的操作系统,在DELPHI2.0中,我
们可以充分利用这一特性, 
编写出“多线程”的应用程序。 
  对以往在DOS或16位windows下写程序的人来说,“多线程”仍然是陌生的,
但如同以前我们从DOS下的单 
任务过渡到windows3.1下的多任务,如今我们又必须过渡到“多线程”领域,毕
竟计算机时代是在不断发展 
的。不过,幸运的是,在DELPHI2.0下进行多线程程序设计并不需要我们去学习
庞大的WIN32API函数,我们 
可以利用DELPHI下标准的多线程类TThread来完成我们的工作。 
  TThread是一个abstract(抽象)类,也就是说,并不需要根据TThread来声
明变量(而且根据TThread声 
明的变量也是完全无用),我们要做的是把TThread作为基类,用继承的形式来生
成子类。实际上,根据 
TThread来写多线程应用程序是非常容易的。 
  下面就是一个基本的继承TThread生成的多线程类。 
  QuerThrd.Pas 
  unitQuerThrd; 
  interface 
  uses 
  Classes,DBTables; 
  type 
  TQueryThreadΚclass(TThread) 
  private 
  fQuery:tQuery; 
  protected 
  procedureExecute;override; 
  public 
  constructorCreate(Suspended:Boolean;Query: 
TQuery); 
  end; 
  implementation 
  constructor 
  TQueryThread.Create(Suspended:Boolean;Quer 
y:TQuery); 
  begin 
  inheritedCreate(Suspended); 
  fQuery:ΚQuery; 
  FreeOnTerminate:ΚTrue; 
  end; 
  procedureTQueryThread.Execute; 
  begin 
  fQuery.Open; 
  end; 
  end. 
  在上面这个简单的例子中,我们构造了一个TThread的子类TQueryThread,
用于在后台执行数据库查 
询。在该类的Create函数中,传递了两个参数Suspended和Query,其中Suspende
d用于控制线程的运行,如果 
Suspend为真,TQueryThread类的线程在建立后将立即被悬挂,一直到运行了Res
ume方法,该线程才会继续执 
行,Query参数用于接受一个已经存在的Query控件(在窗体中真正的Query控件)
而使它在多线程的情况下运 
行。Execute是最重要的过程,它是类TQueryThread的执行部分,所有需要在这个
多线程类中运行的语句都必 
须写在这个过程里。 
  实际上构造自己的多线程类时,并不需要输入所有的这些代码,选择DELPHI
的File菜单下的new选项,再 
选“TThreadObject”项目,DELPHI就会为你构造基本的程序模块。然后我们可以
根据需要再做相应的修改。 
  进程的执行: 
  假设我们已经建立了一个窗体FORM1,窗体中有我们将要使用的查询控件Que
ry1。那么我们在该单元的 
USES部分加入上面写的QuerThrd单元。 
  procedureTForm1.Button1Click(Sender:TObject); 
  begin 
  {建立一个运行的进程} 
  TQueryThread.Create(False,Query1); 
  end; 
  如果这个过程被执行,那么窗体中的查询控件Query1就会自动在多线程的环
境下运行查询。注意 
TQueryThread类中只有Create而没有Free,动态建立类以后又忘记删除是我们常
犯的错误之一,不过在这里 
由于我们指定了FreeOnTerminate(运行完即删除)为真,所以当Execute里的语
句执行完后,TQueryThread 
类占据的内存控件将被自动释放。 
  然而还有一个问题值得我们注意,由于同一时刻可以有多个线程同时运行,
那么我们还必须解决好同步 
的问题,如果几个多线程程序之间没有任何关联,那么它们之间也不会有任何冲
突。但实际上,可能同时运 
行几个多线程的数据库应用程序,由于需要共享相同的数据库资源,我们还需要
为Query1增加一个Tsession 
控件。 
  其实,虽然我们也许没有亲自使用过Session控件,但实际上,在所有的数据
库访问时DELPHI都会自动建 
立一个临时的Session控件,使用完后又动态地删除掉它。在平常的数据库编程时
,用不着我们亲自来操作, 
但在数据库多线程执行的情况下,为了不相互冲突,我们必须为每个数据库访问
都定制自己的Session控件。 
这个步骤非常简单,我们只需要在窗体中增加一个Session控件,然后给它的属性
“Sessionname”写一个任 
意的名字,并再在Query1的“Sessionname”中写一个相同的名字。这样我们的数
据库程序就安全了。 
  另一类需要解决同步问题的是那些对VCL资源进行操作的程序,这类的程序非
常多,好在解决的方法也非 
常简单。 
  我们可以看下面这样一个程序: 
  unitBncThrd; 
  interface 
  uses 
  WinProcs,Classes,Graphics,ExtCtrls; 
  type 
  TBounceThreadΚclass(TThread) 
  private 
  FShape:TShape; 
  FXSpeed:Integer; 
  FYSpeed:Integer; 
  procedureMoveShape; 
  protected 
  procedureExecute;override; 
  public 
  constructorCreate(Suspended:Boolean;Shape:TShape;XSpeed,YSpe
ed:Integer); 
  propertyShape:TShapereadFShape; 
  end; 
  implementation 
  procedureTBouad.MoveShape; 
  var 
  MaxHeight,MaxWidth:Integer; 
  begin 
  withFShapedo 
  begin 
  Left:ΚLeft+FXSpeed; 
  Top:ΚTop+FYSpeed; 
  if(LeftΙ0)or 
  (Left+WidthΛParent.Width)then 
  FXSpeed:ΚFXSpeed*-1; 
  if(TopΙ0)or 
  (Top+HeightΛParent.Height)then 
  FYSpeed:ΚFYSpeed*-1; 
  end; 
  end; 
  procedureTBounceThread.Execute; 
  begin 
  WhilenotTerminateddo 
  begin 
  Synchronize(MoveShape); 
  end; 
  end; 
  constructorTBounceThread.Create(Suspended:Boolean;Shape:TShap
e;XSpeed,YSpeed: 
Integer); 
  begin 
  inheritedCreate(Suspended); 
  FShape:ΚShape; 
  FXSpeed:ΚXSpeed;{X轴走向的速度} 
  FYSpeed:ΚYSpeed;{Y轴走向的速度} 
  FreeOnTerminate:ΚTrue; 
  end; 
  end. 
  这是一个多线程的碰碰球游戏,你可以有多个不同的球,它们分属不同的线
程,各自独立的在屏幕上碰 
撞。显然,由于多个球运行的显示会同时操作VCL资源,为了安全,我们在Execu
te过程中的执行部分加入了 
Synchronize(MoveShape)来调用MoveShape过程,实际上,在任何需要操作V
CL资源的地方,例如窗体、 
位图,都应加入Synchronize调用。 
  执行时我们可以新建一个程序,然后在USES部分加入以上的BncThrd单元,再
在它的窗体FORM1上加入两 
个Shape控件Shape1和Shape2,Shape1可以是一个矩形而Shape2是一个圆。加入以
下的代码就可以让矩形和圆 
动起来。 
  procedureTForm1.Button1Click(Sender:TObject); 
  begin 
  TBounceThread.Create(False,Shape1,1,2); 
  TBounceThread.Create(False,Shape2,2,3); 
  end;
 
 [原文转载 北京社区精华区]

[关闭][返回]