****************************************************************
****************************************************************
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.
|