****************************************************************
**************************************************************** TThread在Classes单元中声明,直接从TObject继承下来的,因为,它不是组件.TThread是个抽象类,所以不能创建TThread的实例,而只能创建其派生类的实例.
利用TThread类来编写多线程应用程序的一般步骤如下:
[步骤一] 从TThread类派生出一个新的线程类. [步骤二] 创建线程对象 [步骤三] 设置线程对象的属性,比如优先级等. [步骤四] 根据具体情况挂起或唤醒线程. [步骤五] 结束线程.
从TThread类派生出一个新的线程类的过程非常简单:通常菜单"File|New|Other..."打开"New Items"对话框,选中"New"页的"Thread Object"项,单击"OK"按钮,接着在弹出的"New Thread Object"对话框中输入新的线程类的名称.通常线程类的名称以T开头,以Thread结束,例如"TTestThread".
TThread类还有以下的一些属性、方法和事件:
Priority属性:整型,设置线程的优先级. Return Value属性:返回值,即当线程结束时返回给其他线程的一个数值. Suspended属性:判断线程是否被挂起. ThreadID属性:线程标识号,是整个系统中线程的标识号. DoTerminate过程:产生一个OnTerminate事件,但是不结束线程的执行. Resume过程:唤醒一个线程继续执行. Suspend过程:挂起一个线程. Synchronize过程:由主VCL线程调用的一个同步过程. Terminate过程:将Terminated属性设置为True,终止线程的执行. WairFor方法:等待线程的终止并返回Return Value属性的数值.
线程优先级的设定:
TThreadPriority = (tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical);
下面进行一个简单的示例:
线程单元:
unit untPaintThread;
interface
uses Classes;
type PaintThread = class(TThread) private { Private declarations } protected procedure Execute; override; end;
implementation
uses untMain,Graphics;
procedure PaintThread.Execute; var x,y: Integer; begin { Place thread code here } Randomize; repeat x := Random(Form1.ClientWidth); y := Random(Form1.ClientHeight); with Form1.Canvas do begin Lock; //使用vcl中的资源的时候进行相应的加锁 try Pixels[x,y] := clBlue; finally Unlock; // 使用完后进行相应的释放 end;
end; until Terminated; end;
end. 主线程单元:
unit untMain;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,untPaintThread, StdCtrls;
type TForm1 = class(TForm) btn1: TButton; btn2: TButton; procedure btn1Click(Sender: TObject); procedure btn2Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } pthread: PaintThread; public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject); begin pthread.Resume;
end;
procedure TForm1.btn2Click(Sender: TObject); begin pthread.Suspend; end;
procedure TForm1.FormCreate(Sender: TObject); begin pthread := PaintThread.Create(true); end;
procedure TForm1.FormDestroy(Sender: TObject); begin pthread.Free; end;
end.
多线程程序访问VCL的时候要特别注意,只能逐个地实现对VCL的访问.具体可以采用下面的两个方法: (1) 锁定VCL对象 对于一些具有锁定功能的对象,可以在锁定之后再进去具体操作,比如上面的方法!!!. (2) 使用Synchronize函数 TThread类的Synchronize过程声明如下:
type TThreadMethod=procedure of object; procedure Synchronize(Method:TThreadMethod);
其他参数Method为一个不带参数的过程名.在这个不带参数的过程中是一些访问VCL的代码. 对Synchronize的调用是在Execute过程中,用来避免对VCL的并发访问.程序运行期间的具体过程实际上是由Synchronize过程来通知主线程,然后主线程在适当的时机执行Synchronize过程的参数列表中不带参数的过程.在多个线程的情况下,主线程将Synchronize过程所发的通知放到消息队列中,然后逐个地响应这些消息.通过这种机制Synchronize实现了线程之间的同步. unit untmain;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Spin, ImgList;
type TAnimThread = class(TThread) private bt: TBitmap; procedure DrawGraphics; protected procedure execute; override;
end; type
TForm1 = class(TForm) il1: TImageList; SpinEdit1: TSpinEdit; lbl1: TLabel; lbl2: TLabel; btn1: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure btn1Click(Sender: TObject); private { Private declarations } public { Public declarations } anmthread: TAnimThread; end;
var Form1: TForm1; run: Boolean;
implementation
{$R *.dfm}
{ TAnimThread }
procedure TAnimThread.DrawGraphics; begin //这个地方使用了双缓冲技术 Form1.Canvas.CopyRect(Bounds(0,0,Form1.Width,32),bt.Canvas,Bounds(0,0,Form1.Width,32)); BitBlt(Form1.Canvas.Handle,0,0,Form1.Width,32,bt.Canvas.Handle,0,0,SRCCOPY); end;
procedure TAnimThread.execute; var x,i: Integer; dir: Boolean; begin bt := TBitmap.Create; try bt.Width := Form1.ClientWidth; bt.Height := 32; bt.Canvas.Pen.Color := clPurple; bt.Canvas.Brush.Color := clSkyBlue; bt.Canvas.Rectangle(0,0,Form1.Width,32); dir := false; x := 0; i := 0; repeat begin Inc(i); bt.Canvas.Rectangle(0,0,Form1.Width,32); Form1.il1.Draw(bt.Canvas,x,0,i); Synchronize(DrawGraphics); Sleep(1* 100); if (i < 0) or(i>300) then dir := not dir; if dir then Inc(x) else Dec(x); if i > Form1.il1.Count - 1 then i := 0; end;
until terminated;
finally bt.Free; end;
end;
procedure TForm1.FormCreate(Sender: TObject); begin run := false; end;
procedure TForm1.FormDestroy(Sender: TObject); begin if not anmthread.Terminated then anmthread.Free; end;
procedure TForm1.btn1Click(Sender: TObject); begin run := not run; if run then begin anmthread := TAnimThread.Create(false); end else anmthread.Free; if btn1.Caption = '开始' then btn1.Caption := '结束' else btn1.Caption := '开始'; end;
end.
|