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参数,这才是它的真正有用之处。