Delphi多线程编程中的技巧(转)

1)创建线程
MsgThread := TMsgThread.Create(False) ; //创建并执行线程
MsgThread := TMsgThread.Create(True) ; //创建线程后挂起
constructor Create(CreateSuspended: Boolean); 中的参数CreateSuspended表示创建后是否挂起线程。
(2)设置线程里没有设置循环执行的话,且设置FreeOnTerminate为True,则线程执行完后就会自己释放。
(3)在一个线程结束后,调用另一个事件的方法:
只要设置Onterminate:=某方法,这样在线程结束前自然会被调用,比如 :

procedure  TSendShortMessageThread.Execute; 
var  
Bitmap: Tbitamp; 
begin  
Bimap:
= Tbitmap.create( nil ) ; 
OnTerminate:
= Threaddone; 
end

procedure  Threaddone(sender: tobject); 
begin  
Bimap.Free; 
// 在Destory之前会被调用 
end

 

(4)程序结束前安全的退出线程的方法:

if  MsgThread  <>   nil   then  
begin  
MsgThread.Terminate ; 
MsgThread.WaitFor ; 
end

 

(5)判断当前线程的状态:

// 以下资料来自大富翁论坛。 
/ 判断线程是否释放 
// 返回值: 0 - 已释放; 1 - 正在运行; 2 - 已终止但未释放; 
// 3 - 未建立或不存在 
function  TFrmMain.CheckThreadFreed(aThread: TThread): Byte; 
var  
i: DWord; 
IsQuit: Boolean; 
begin  
if  Assigned(aThread)  then  
begin  
IsQuit :
=  GetExitCodeThread(aThread.Handle, i); 
if  IsQuit  then   // If the  function  succeeds, the return value  is  nonzero. 
// If the  function  fails, the return value  is  zero. 
begin  
if  i  =  STILL_ACTIVE  then   // If the specified thread has  not  terminated, 
// the termination status returned  is  STILL_ACTIVE. 
Result :
=   1  
else  
Result :
=   2 // aThread未Free,因为Tthread.Destroy中有执行语句 
end  
else  
Result :
=   0 // 可以用GetLastError取得错误代码 
end  
else  
Result :
=   3
end

 

(6)线程同步。
如果线程要调用VCL里面的内容(如:别的窗体中的控件),就需要将这个线程同步。线程同步表示交由主线程运行这段代码,各个线程都在主线程中分时间段运行。另外,要想避免多个线程同时执行同一段代码也需要将多线程同步。
临界区和互斥的作用类似,都是用来进行同步的,但它们间有以下一点差别:
临界区只能在进程内使用,也就是说只能是进程内的线程间的同步;而互斥则还可用在进程之间的;临界区所花消的时间很少,才10~15个时间片,而互斥需要400多个;临界区随着进程的终止而终止,而互斥,如果你不用closehandle()的话,在进程终止后仍然在系统内存在,也就是说它是系统全局对象;
同步的方法有:

(1)使用临界区对象。
临界区对象有两种:TRTLCriticalSection 和 CriticalSection。
?? TRTLCriticalSection的用法

var
GlobalVariable:Double;

var
CriticalSection:TRTLCriticalSection;

procedure SetGlobalVariable(Value:Double);
begin
EnterCriticalSection(CriticalSection); //进入临界区
try
GlobalVariable:=Value;
finally
LeaveCriticalSection(CriticalSection); //离开临界区
end;
end;

initialization
InitializeCriticalSection(CriticalSection); //初始化
finalization
DeleteCriticalSection(CriticalSection); //删除
end.
?? CriticalSection(重要区段)的用法:
var criticalsection: TCriticalsection;

创建:criticalsection := TCriticalsection.create;

使用:
criticalsection.enter;
try
...
finally
criticalsection.leave;
end;

(2)使用互斥
先在主线程中创建事件对象:
var
hMutex: THandle = 0;
...
hMutex := CreateMutex(nil, False, nil);

在线程的Execute方法中加入以下代码:
if WaitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 then
//Do Something;
...
ReleaseMutex(hMutex);

最后记得要释放互斥对象:
CloseHandle(hMutex);

(3)使用信号量

unit  Unit1; 

interface  

uses  
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 
Dialogs, ExtCtrls, StdCtrls; 

type  
TForm1 
=   class (TForm) 
Edit1: TEdit; 
Button1: TButton; 
procedure  FormCreate(Sender: TObject); 
procedure  FormDestroy(Sender: TObject); 
procedure  Button1Click(Sender: TObject); 
private  
{  Private declarations  }  
public  
{  Public declarations  }  
end

type  
TMyThread 
=   class (TThread) 
private  

protected  
procedure  Execute;  override
public  

constructor  Create;  virtual
end

var  
Form1 : TForm1; 
HSem : THandle 
=   0  ; 
implementation  

{ $R *.dfm }  

var  
tick: Integer 
=   0
procedure  TMyThread.Execute; 
var  
WaitReturn : DWord ; 
begin  
WaitReturn :
=  WaitForSingleObject(HSem,INFINITE) ; 
Form1.Edit1.Text :
=  IntToStr(tick); 
Inc(tick); 
Sleep(
10 ); 
ReleaseSemaphore(HSem, 
1 , Nil) 
end

constructor  TMyThread.Create; 
begin  
inherited  Create(False); 
FreeOnTerminate :
=  True; 
end

procedure  TForm1.FormCreate(Sender: TObject); 
begin  
HSem :
=  CreateSemaphore(Nil, 1 , 1 ,Nil) ; 

end

procedure  TForm1.FormDestroy(Sender: TObject); 
begin  
CloseHandle(HSem) ; 
end

procedure  TForm1.Button1Click(Sender: TObject); 
var  
index: Integer; 
begin  
for  index : =   0   to   10   do  
begin  
TMyThread.Create; 
end
end ;
end

 


一般的同步对象使用Mutex对象,是因为Mutex有一个特别之处:当一个持有对象的线程DOWN掉的时候,mutex对象可以自动让其它等待这个对象的线程接受,而其它的内核对象则不具体这个功能。
之所要使用Semaphore则是因为Semaphore可以提供一个活动线程的上限,即lMaximumCount参数,这才是它的真正有用之处。

转载于:https://www.cnblogs.com/rogee/archive/2010/09/20/1831991.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值