Delphi的多线程开发实例

在软件开发的过程中,多线程的开发应用有着极为重要的位置,使用多线程可以让软件系统

能够并行操作、同时也能提高其运行效率。作为软件开发人员的必修课之一,多线程的熟练

运用可以让软件系统有更佳的性能表现。

以下使用Window Api、Delphi 封装的TThread类来分别创建线程,再以普通方法来执行

一个耗时的过程,对比使用线程的好处。


1. Windows API 函数直接创建
   主要是CreateThread 函数,其函数式如下:
    HANDLE CreateThread(
        // 线程安全属性,默认用Nil
        LPSECURITY_ATTRIBUTES lpThreadAttributes,
        // 线程分配的堆栈大小,默认为0,系统自动分配 
        DWORD dwStackSize,      
        // 线程函数入口地址,要求是不带参数的全局性的方法
        LPTHREAD_START_ROUTINE lpStartAddress,
        // 传递给线程的参数值 
        LPVOID lpParameter,
        // 创建线程的标识,如CREATE_SUSPENDED (挂起)
        DWORD dwCreationFlags, 
        //返回的线程标识identifier
        LPDWORD lpThreadId     
        ); 
如果线程创建成功,返回值为其句柄值 .

在Delphi 项目中新建一个窗体,写下以下线程函数,以便调用
procedure APIThread1;
var i,cId:Integer;
begin
   with Form2 do
   begin
      for i:=1 to imax do
      begin
        EnterCriticalSection(Rtl);
        cId := GetCurrentThreadId ; //获取当前执行的线程标识
        Memo1.Lines.Add('Thread ID '+inttostr(cId)+ ' : '+inttostr(i));
        LeaveCriticalSection(Rtl);
      end;
   end;
end;

为防止多个线程同时访问(读写)同一个VCL资源引起出错,使用了临界变量 Rtl,
所以要声明一个局部的临界变量
Var
  Rtl : TRTLCriticalSection;

其作用相当于一个协议锁,比如: 当APIThread1 函数,被CreateThread

(nil,0,@APIThread1,nil,0,hid)
调用多次产生不同线程时,由于都对Memo1 执行了写入操作,其中一个线程在写入的过

程中,用Rtl临界变量告诉其它正要访问的线程:"我正在使用,请稍等。"
 
注意:
进入临界区EnterCriticalSection(Rtl) 和离开临界区LeaveCriticalSection(Rtl)是
配对的,所以要确保正常进入,正常离开,在使用临界区变量前,必需先初始化,

InitializeCriticalSection(Rtl),用完后释放DeleteCriticalSection(Rtl);


2.  使用Delphi 封装的TThread 类创建
     主要是继承TThread 类,在TThread 类的核心方法Execute中执行你想要的操作代码.
其实,通过查看TThread 类的源代码可知,TThread同样是调用CreateThread函数创建线

程,只是封装/简化了部分线程的应用细节,同时也纳入部分安全考虑,这无疑为开发人

员提供了调用上的方便。
     方法中常用的线程挂起Suspend,唤醒Resume,中止Terminate等方法,可查阅相关

资料说明,这里仅作线程的简单调用例子。
  
先声明继承类
type
  TMyThread =class(TThread)

  private
    FFlag:Integer;
    procedure AccessVcl;
  protected
    procedure Execute ; override;
  public
     constructor Create(aFlag:Integer);
  end;

在implementation部分写下方法内容
constructor TMyThread.Create(aFlag: Integer);
begin
  inherited Create(Suspended) ;
  FreeOnTerminate := true;
  FFlag := aFlag;
end;

procedure TMyThread.Execute;
begin
  inherited;
  AccessVcl;
  //Synchronize(AccessVcl);
end;

procedure TMyThread.AccessVcl;
var i:Integer;
begin
   with Form2 do
   begin
      for i:=1 to iMax do
        Memo1.Lines.Add('My Thread '+Inttostr(FFlag)+' : '+inttostr(i));
   end;
end;

调用执行线程:TMyThread.Create(10);

3. 再写一个普通的for 循环执行某个比较花费时间的操作方法
  for i:=1 to imax do
  begin
    cId := GetCurrentThreadId ;
    Memo1.Lines.Add('Thread ID '+inttostr(cId)+ ' : '+inttostr(i));
  end;

在窗体上分别调用API 线程方法,Delphi TThread 线程类方法,普通操作方法,再比较

执行效果,即时可以体现线程方法与非线程的好处。

 

全部源码如下:

view plaincopy to clipboardprint?
unit Unit2;  
 
interface 
 
uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  Dialogs, StdCtrls;  
 
type 
  TForm2 = class(TForm)  
    Memo1: TMemo;  
    BtnThread1: TButton;  
    BtnThread2: TButton;  
    BtnNoThread: TButton;  
    Button1: TButton;  
    BtnClear: TButton;  
    BtnMyThread: TButton;  
    Button2: TButton;  
    procedure BtnThread1Click(Sender: TObject);  
    procedure BtnThread2Click(Sender: TObject);  
    procedure BtnNoThreadClick(Sender: TObject);  
    procedure Button1Click(Sender: TObject);  
    procedure BtnClearClick(Sender: TObject);  
    procedure BtnMyThreadClick(Sender: TObject);  
    procedure Button2Click(Sender: TObject);  
  private 
    { Private declarations } 
  public 
    { Public declarations } 
  end;  
 
{继承的线程类} 
type 
  TMyThread =class(TThread)  
 
  private 
    FFlag:Integer;  
    procedure AccessVcl;  
  protected 
    procedure Execute ; override;  
 
  public 
     constructor Create(aFlag:Integer);  
  end;  
 
const 
   iMax = 2000 ;  
 
var 
  Form2: TForm2;  
  Rtl : TRTLCriticalSection;  
  Thd1,Thd2 : Cardinal;  
 
implementation 
 
{$R *.dfm} 
 
//API 线程方法  
procedure APIThread1;  
var i,cId:Integer;  
begin 
   with Form2 do 
   begin 
      for i:=1 to imax do 
      begin 
        EnterCriticalSection(Rtl);  
        cId := GetCurrentThreadId ;  
        Memo1.Lines.Add('Thread ID '+inttostr(cId)+ ' : '+inttostr(i));  
        LeaveCriticalSection(Rtl);  
      end;  
   end;  
end;  
 
constructor TMyThread.Create(aFlag: Integer);  
begin 
  inherited Create(Suspended) ;  
  FreeOnTerminate := true;  
  FFlag := aFlag;  
end;  
 
procedure TMyThread.Execute;  
begin 
  inherited;  
  AccessVcl;  
  //Synchronize(AccessVcl);  
end;  
 
procedure TMyThread.AccessVcl;  
var i:Integer;  
begin 
   with Form2 do 
   begin 
      for i:=1 to iMax do 
        Memo1.Lines.Add('My Thread '+Inttostr(FFlag)+' : '+inttostr(i));  
   end;  
end;  
 
procedure TForm2.BtnThread1Click(Sender: TObject);  
var Hid:THandle;  
begin 
  //API线程调用1  
  Thd1:= CreateThread(nil,0,@APIThread1,nil,0,hid);  
end;  
 
procedure TForm2.BtnThread2Click(Sender: TObject);  
var Hid:THandle;  
begin 
  //API线程调用2  
  Thd2:= CreateThread(nil,0,@APIThread1,nil,0,hid);  
end;  
 
procedure TForm2.BtnNoThreadClick(Sender: TObject);  
var i,cid:Integer;  
begin 
  //普通方法执行for 循环  
  for i:=1 to imax do 
  begin 
    cId := GetCurrentThreadId ;  
    Memo1.Lines.Add('Thread ID '+inttostr(cId)+ ' : '+inttostr(i));  
  end;  
end;  
 
procedure TForm2.Button1Click(Sender: TObject);  
begin 
   ShowMessage('同时执行其它操作');  
end;  
 
procedure TForm2.BtnClearClick(Sender: TObject);  
begin 
  Memo1.Lines.Clear;  
end;  
 
procedure TForm2.BtnMyThreadClick(Sender: TObject);  
begin 
  //Delphi TThread继承类的调用方法  
  TMyThread.Create(11);  
end;  
 
procedure TForm2.Button2Click(Sender: TObject);  
var ext:THandle;  
begin 
  GetExitcodeThread(Thd1,Ext);  
  TerminateThread(Thd1,ext);  
  //LeaveCriticalSection(Rtl);  
end;  
 
initialization 
    InitializeCriticalSection(Rtl);  
 
finalization 
    DeleteCriticalSection(Rtl);  
 
end. 

 

你可能感兴趣的:(delphi)