多線程編程中的技巧

來源:互聯網
上載者:User

(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。
&#61548;  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.
&#61548;  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參數,這才是它的真正有用之處。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.