Chinaunix首页 | 论坛 | 博客
  • 博客访问: 234974
  • 博文数量: 73
  • 博客积分: 3005
  • 博客等级: 中校
  • 技术积分: 857
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-24 10:11
文章分类

全部博文(73)

文章存档

2014年(2)

2011年(5)

2010年(29)

2009年(32)

2008年(5)

我的朋友

分类:

2009-12-08 09:39:48

Delphi多线程编程中的技巧
 
一.创建线程
  MsgThread := TMsgThread.Create(False) ; //创建并执行线程
  MsgThread := TMsgThread.Create(True) ; //创建线程后挂起
  constructor Create(CreateSuspended: Boolean); 中的参数CreateSuspended表示创建后是否挂起线程。
二.设置线程里没有设置循环执行的话,且设置FreeOnTerminate为True,则线程执行完后就会自己释放。
三.在一个线程结束后,调用另一个事件的方法:
  只要设置Onterminate:=某方法,这样在线程结束前自然会被调用,比如 :
procedure TSendShortMessageThread.Execute;
var
  Bitmap: Tbitamp;
begin
  Bimap:=Tbitmap.create(nil) ;
  OnTerminate:=Threaddone;
end;
 
procedure Threaddone(sender: tobject);
begin
  Bimap.Free; //在Destory之前会被调用
end;
四.程序结束前安全的退出线程的方法:
if MsgThread <> nil then
begin
  MsgThread.Terminate ;
  MsgThread.WaitFor ;
end;
五.判断当前线程的状态:
//以下资料来自大富翁论坛。
/判断线程是否释放
//返回值: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 the function succeeds, the return value is nonzero.
    if IsQuit then
    //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;
六.线程同步。
  如果线程要调用VCL里面的内容(如:别的窗体中的控件),就需要将这个线程同步。线程同步表示交由主线程运行这段代码,各个线程都在主线程中分时间段运行。另外,要想避免多个线程同时执行同一段代码也需要将多线程同步。
临界区和互斥的作用类似,都是用来进行同步的,但它们间有以下一点差别:
临界区只能在进程内使用,也就是说只能是进程内的线程间的同步;而互斥则还可用在进程之间的;临界区所花消的时间很少,才10~15个时间片,而互斥需要400多个;临界区随着进程的终止而终止,而互斥,如果你不用closehandle()的话,在进程终止后仍然在系统内存在,也就是说它是系统全局对象;
同步的方法有:
  1.使用临界区对象。
  临界区对象有两种:TRTLCriticalSection 和 CriticalSection。
  (1) 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); //删除
 
  (2)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参数,这才是它的真正有用之处。

 
阅读(393) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~