補充: 多線程編程知識 (多線程是必須逾越過去~~)

補充: 多線程編程知識  (多線程是必須逾越過去~~)

  1. 示例 :

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to 500000 do
  begin
    Canvas.TextOut(10, 10, IntToStr(i));
    Application.ProcessMessages;  // 一般在比較費時的循環中加入 ProcessMessages,以便可以響應其他消息 ~~ 不是多線程
  end;
end;

  標準線程 :


 a. > 調用 API 創建線程

  function myfun(p : Pointer) : integer;stdcall;
  var
    i : integer;
  begin
    for i := 1 to 500000 do
    begin
      Form1.Canvas.Lock;  //  多線程中必須加鎖
      Form1.Canvas.Textout(100,200,Inttostr(i));
      Form1.Canvas.Unlock;  // 解鎖
    end;
    Result := 0;
  end;
 
  var ID : THandle;

  CreateThread(nil,0,@myfun,nil,0,ID); // 調用 API 創建線程,新建線程執行方法 myfun;
 
  CreateThread 第三個參數是函數指針,新建的線程建立後立即執行該函數,函數執行完後立即銷毀此線程。
  調用的函數必須系統級的,不能屬於某一個類的函數,因此必須加上 stdcall,並且必須具有給定的(參數,返回值)格式,即使用不上也要加上。
  CreateThead還必須接受函數的 THandle。
 
 
  B. > TThread 類

  Type TMyThread = class(TThread)  // TThread 是一個抽像類,必須繼承使用
  protected
     procedure Execute; override;
  end;

  procdure TMyThread.Execute;
  var
    i : Integer;
  begin
    inherited;
    FreeOnTerminate := True;  // 線程執行完後立即結束
    For i :=0 to 500000 then
    begin
      Form1.Canvas.Lock;  //  多線程中必須加鎖
      Form1.Canvas.Textout(100,200,Inttostr(i));
      Form1.Canvas.Unlock;  // 解鎖     
    end;
  end;

procdure TForm1.Button1Click (Sender : TObject);
var
  MyThread : TMyThread;
begin
  MyThread := TMyThread.Create(false);
end;

CreateThread 另外可參見 CreateRemoteThread (建立其它進程中的線程)
CreateThread 返回線程句柄;句柄類似於指針,但句柄只是用來使用對象;有句柄的對象一般為內核對象。
當有多個線程在運行時,系統自動在每個線程中切換執行;線程的數據狀態保持在結構 TContext 中,其相對於一個 CPU寄存器的集合,
可以通過 GetThreadContent 獲得。

線程句柄 and 線程ID : 線程ID 是唯一的;而句柄可以有多個,GetCurrentThread 返回的是一個偽句柄,DuplicateHandle 用來複製一個句柄。
在主線程中 ,GetCurrentThreadID,MainThreadID,MainInstance 返回的是主線程ID。

function CreateThread(
  lpThreadAttributes: Pointer;
  dwStackSize: DWORD;
  lpStartAddress: TFNThreadStartRoutine;
  lpParameter: Pointer;
  dwCreationFlags: DWORD;   // 啟動選項
  var lpThreadId: DWORD
): THandle; stdcall;

  dwCreationFlags : 啟動選項,有2個值:

  0 : 線程建立後立即執行入口函數;

  CREATE_SUSPENDED : 線程建立後掛起等待;
  可用 ResumeThread恢復線程執行; SuspendedThread 再次掛起;

  第四個參數: 線程入口函數的參數 -- lpParameter, 可以指定任何參數。

  第三個參數: lpStartAddress 入口函數指針, DWORD 類型 .
  可以使用 GetExitCodeThread 函數獲得退出碼,即為此返回值.
  ** 入口函數不能為類的方法。

  第二個參數: dwStackSize: DWORD; 分配給線程的堆棧大小。
  第一個參數: lpThreadAttributes : 安全設置, 其指向 TSecurityAttributes結構,
  一般為 nil , 表示沒有訪問限制 .

  線程同步一般使用四個系統內核對象:
  1. 事件 -- CreateEvent;
  2. 互斥 -- CreateMutex;
  3. 信號 -- CreateSemaphore;
  4. 計時器--CreateWaitableTimer;

  比較簡單的同步手段是 CriticalSection (臨界區),其不屬於內核對象,沒有句柄,也不需要跨進程使用。

// 臨界區示例 ****** 
  定義臨界區: CS : TRTLCriticalSection ;
  在線程函數中加入:
  EnterCriticalSection(CS);
  ...
  LeaveCriticalSection(CS);

  FormCreate 中 : InitializeCriticalSection(CS);
  FormDestory中 : DeleteCriticalSectioin(CS);
// 臨界區示例 ******

  等待函數 : WaitForSingleObject

function WaitForSingleObject(
  hHandle: THandle;      {要等待的對象句柄}
  dwMilliseconds: DWORD  {等待的時間--毫秒}
): DWORD; stdcall;  

  返回值如下:
  WAIT_OBJECT_0 : 剛好等著了
  WAIT_TIMEOUT  : 等過了點
  WAIT_ABANDONED: 互斥對象不讓執行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值