首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

多線程程式設計(2) - 從 CreateThread 說起:線程句柄、ID、上下文結構與 ExitThread 陷阱

     編輯:Delphi

本文系統梳理 CreateThread 完整參數列表,重點剖析返回值「線程句柄」與輸出參數「線程 ID」的本質差異、內核對象安全模型、線程上下文切換結構 TContext,並揭示 ExitThread 在主線程與 TThread 中的使用陷阱。

CreateThread 完整簽名回顧

function CreateThread(
  lpThreadAttributes: Pointer; { 安全屬性 }
  dwStackSize: DWORD;          { 堆疊大小 }
  lpStartAddress: TFNThreadStartRoutine; { 入口函數 }
  lpParameter: Pointer;        { 函數參數 }
  dwCreationFlags: DWORD;      { 啟動選項 }
  var lpThreadId: DWORD        { 輸出線程 ID }
): THandle; stdcall;           { 返回線程句柄 }

Delphi TThread.Create → BeginThread → CreateThread 層層封裝。

ExitThread 陷阱:為什麼不建議手動呼叫

procedure TForm1.Button1Click(Sender: TObject);
begin ExitThread(0); { 直接退出主線程,進程隨之終止 } end;
  • 進程 = 環境,線程 = 工作者。主線程結束 ⇒ 進程結束。
  • CreateThread 入口函數執行完自動退出,無需 ExitThread。
  • TThread 分配了額外資源(成員變數、TObject 基礎結構),若用 ExitThread 強制退出會導致記憶體洩漏。Delphi 提供 EndThread 但同樣不建議手動調用——你很難知道線程何時真正跑完。

線程句柄 vs 線程 ID

線程上下文切換:TContext 結構

系統分時調度時,將 CPU 寄存器狀態保存/恢復於 TContext(CONTEXT)結構:

_CONTEXT = record
  ContextFlags: DWORD;
  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7: DWORD; { 偵錯寄存器 }
  FloatSave: TFloatingSaveArea;        { FPU/SSE 狀態 }
  SegGs, SegFs, SegEs, SegDs: DWORD;   { 區段寄存器 }
  Edi, Esi, Ebx, Edx, Ecx, Eax: DWORD; { 通用寄存器 }
  Ebp, Eip: DWORD;                     { 基址指標、指令指標 }
  SegCs, EFlags, Esp, SegSs: DWORD;    { 程式碼段、標誌、堆疊指標、堆疊段 }
end;

可用 GetThreadContext/SetThreadContext 讀寫,實現線程劫持、偵錯器斷點等高階功能。

總結

  1. 掌握 CreateThread 六參數含義,是多線程編程基石。
  2. 句柄用於操作,ID 用於識別;兩者互補。
  3. 避免手動 ExitThread/EndThread,讓線程自然結束或用 TThread 托管生命週期。
  4. 理解 TContext 為後續學習線程調試、上下文切換鋪路。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性句柄ID
本質內核對象引用(不透明指標)系統唯一數值標識符
唯一性可複製(DuplicateHandle)、偽句柄(GetCurrentThread)全系統唯一,不可重複
輕量度含權限、引用計數等單純 32 位整數,更輕便
取得主線程GetCurrentThread(偽句柄)GetCurrentThreadId、MainThreadID