孤独的猫

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Delphi把多线程相关的API封装在TThread这个类中,可以方便实现多线程运用。首先看下TThread的声明:

  1. TThread = class   
  2.    
  3. private   
  4.   FHandle: THandle;    
  5.   FThreadID: THandle;    
  6.   FCreateSuspended: Boolean;    
  7.   FTerminated: Boolean;    
  8.   FSuspended: Boolean;    
  9.   FFreeOnTerminate: Boolean;    
  10.   FFinished: Boolean;   
  11.   FReturnValue: Integer;   
  12.   FOnTerminate: TNotifyEvent;    
  13.   FSynchronize: TSynchronizeRecord;   
  14.   FFatalException: TObject;   
  15.   procedure CallOnTerminate;   
  16.   class procedure Synchronize(ASyncRec: PSynchronizeRecord); overload;   
  17.   function GetPriority: TThreadPriority;   
  18.   procedure SetPriority(Value: TThreadPriority);   
  19.   procedure SetSuspended(Value: Boolean);   
  20.    
  21. protected   
  22.   procedure CheckThreadError(ErrCode: Integer); overload;   
  23.   procedure CheckThreadError(Success: Boolean); overload;   
  24.   procedure DoTerminate; virtual;   
  25.   procedure Execute; virtual; abstract;   
  26.   procedure Synchronize(Method: TThreadMethod); overload;   
  27.   property ReturnValue: Integer read FReturnValue write FReturnValue;   
  28.   property Terminated: Boolean read FTerminated;   
  29.    
  30. public   
  31.   constructor Create(CreateSuspended: Boolean);   
  32.   destructor Destroy; override;   
  33.   procedure AfterConstruction; override;   
  34.   procedure Resume;   
  35.   procedure Suspend;   
  36.   procedure Terminate;   
  37.   function WaitFor: LongWord;   
  38.   class procedure Synchronize(AThread: TThread; AMethod: TThreadMethod); overload;   
  39.   class procedure StaticSynchronize(AThread: TThread; AMethod: TThreadMethod);   
  40.   property FatalException: TObject read FFatalException;   
  41.   property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;   
  42.   property Handle: THandle read FHandle;   
  43.   property Priority: TThreadPriority read GetPriority write SetPriority;   
  44.   property Suspended: Boolean read FSuspended write SetSuspended;   
  45.   property ThreadID: THandle read FThreadID;   
  46.   property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;   
  47. end;    

 

由于TThread是一个抽象类,所以不能直接创建实例,要创建其派生类的实例。

一般的使用流程是这样的:

1、先新建一个以TThread为父类的派生类;

2、覆写构造函数,将特定的参数传递进来,保有存为类的私有变量;

3、覆写Execute方法,将线程要实现的操作放到这个过程中;

4、如果需要与主线程VCL同步的话,调用Synchronize方法;

5、Execute执行完后线程自行终止,如果指定了终止事件则执行OnTerminate指定的过程。

      来一个例子:主窗体上画一个位图BitMap,点击Button1就创建一个线程,线程在位图左边逐像素拷贝出一个相同的位图,同时主窗体的进度条显示拷贝的进度。点击Button2可以随时中止这个拷贝线程。线程中止后,执行一个自定义的中止事件。

 

[delphi:firstline[1]] view plaincopyprint?
  1. unit Demo;  
  2.    
  3. interface  
  4.    
  5. uses  
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  7.   Dialogs, ComCtrls, StdCtrls;  
  8.    
  9. type  
  10.   TForm2 = class(TForm)  
  11.     Button1: TButton;  
  12.     ProgressBar1: TProgressBar;  
  13.     Button2: TButton;  
  14.     Edit1: TEdit;  
  15.     procedure FormCreate(Sender: TObject);  
  16.     procedure FormPaint(Sender: TObject);  
  17.     procedure FormDestroy(Sender: TObject);  
  18.     procedure Button1Click(Sender: TObject);  
  19.     procedure Button2Click(Sender: TObject);  
  20.     procedure TerminatedProc(Sender:TObject);//线程终止时执行的过程   
  21.   private  
  22.     { Private declarations }       
  23.   public  
  24.     { Public declarations }  
  25.   end;  
  26. type  
  27.   TCopyThread = Class(TThread)  
  28.   private  
  29.     FPoint:TPoint;  
  30.     procedure UpdateProgressBar; //用于同步主线程的进度条   
  31.   protected  
  32.     procedure Execute;Override;  
  33.   public  
  34.     Constructor Create(p:TPoint);  
  35.   End;  
  36.    
  37.    
  38. var  
  39.   Form2: TForm2;  
  40.   CopyThread:TCopyThread;  
  41. implementation  
  42.    
  43. {$R *.dfm}  
  44. var  
  45.   BitMap:TBitMap;  
  46. {TForm2类}  
  47. procedure TForm2.Button1Click(Sender: TObject);  
  48. var  
  49.   p:TPoint;     
  50. begin  
  51.   p.X:=BitMap.Width;  
  52.   P.Y:=0;  
  53.   CopyThread:=TCopyThread.Create(p);  
  54.   CopyThread.OnTerminate:=TerminatedProc;//指定线程终止时执行的过程   
  55.   ProgressBar1.Max:=BitMap.Width*BitMap.Height;  
  56.   ProgressBar1.Position:=0;  
  57. end;  
  58.    
  59. procedure TForm2.Button2Click(Sender: TObject);  
  60. begin  
  61.  if Assigned(CopyThread) then  
  62.    begin  
  63.      CopyThread.Terminate;  
  64.    end;  
  65. end;  
  66.    
  67. procedure TForm2.FormCreate(Sender: TObject);  
  68. begin  
  69.   BitMap:= TBitmap.Create;  
  70.   BitMap.LoadFromFile('c:/car.bmp');  
  71. end;  
  72.    
  73. procedure TForm2.FormDestroy(Sender: TObject);  
  74. begin  
  75.   BitMap.Free;  
  76. end;  
  77.    
  78. procedure TForm2.FormPaint(Sender: TObject);  
  79. begin  
  80.   Self.Canvas.Draw(0,0,BitMap);  
  81. end;  
  82.    
  83. procedure TForm2.TerminatedProc;  
  84. begin  
  85.   MessageBox(Handle,'线程已终止','提示信息',MB_OK);  
  86. end;  
  87.    
  88. { TCopyThread类 }  
  89. constructor TCopyThread.Create(p: TPoint);  
  90. begin  
  91.   FPoint:=p;  
  92.   inherited Create(False);  
  93. end;  
  94.    
  95. procedure TCopyThread.Execute;  
  96. var  
  97.   i,j:Integer;  
  98.   dot:TColorRef;  
  99.   DC:HDC;  
  100. begin  
  101.   FreeOnTerminate:=True; //线程执行完后自动释放对象资源   
  102.   DC:=GetDC(Form2.Handle);  
  103.   for i := 0 to BitMap.Width - 1 do  
  104.     for j := 0 to BitMap.Height - 1 do  
  105.       if not Terminated then    //如果线程没有终止(放上这句为了随时可以终止线程)   
  106.         begin  
  107.           //为了执行时间久一点,所以逐个像素拷贝   
  108.           dot:=GetPixel(DC,i,j);  
  109.           SetPixel(DC,i+FPoint.X,j+FPoint.Y,dot);  
  110.           Synchronize(UpdateProgressBar); //与主线程VCL同步   
  111.         end;  
  112. end;  
  113. procedure TCopyThread.UpdateProgressBar;  
  114. begin  
  115.   Form2.ProgressBar1.Position:=Form2.ProgressBar1.Position+1;  
  116. end;  
  117.    
  118. end.  

 

说明:1、线程类可以单独放在一个单元中,与主窗体互相Uses。

         2、线程类的Create构造函数中,可以根据需要传入多个任意类型的参数,而不像CreateThread这个API函数中只能传入一个指针。

         3、线程的Excecute过程中,最好加上if not Terminated then 不停地检查是线程是否被终止,这样可以在线程未执行完成前终止线程。

         4、Synchronize过程,与主线程VCL同步,其实其中的方法是由主线程来执行的,所以Synchronize的参数方法UpdateProgressBar执行的越少越好。不要将执行耗时的操作放到这里,否则跟单线程一样,窗体会“死”掉。可以试验一下,将像素拷贝工作这个循环放到UpateProgressBar过程里,这样执行的时候,无法再进行其他操作(如Edit框中输入东东)。

         5、线程的OnTerminate指定的子程序,应该是主线程的成员,因为它是由主线程执行的。这个子程序必须加入相应的参数格式如(Sender :TObject),否则不能编译通过。

posted on 2012-03-06 20:36  孤独的猫  阅读(720)  评论(0)    收藏  举报