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

Delphi 多線程程式設計 (14):WaitableTimer 等待定時器 - 核心 API 詳解與基礎同步範例

     編輯:Delphi

WaitableTimer (等待定時器) 是 Windows 核心同步物件之一,結合**高精度定時**與**線程同步**能力。本文系統整理其建立與設定 API、關鍵參數語意 (手動/自動重置、起始時間、週期、APC 回調、系統喚醒),並提供兩個基礎同步範例:單次觸發喚醒多線程、週期觸發單線程。

核心 API 完整聲明

function CreateWaitableTimer(
  lpTimerAttributes: PSecurityAttributes;  // 安全屬性,通常 nil
  bManualReset: BOOL;                      // True=手動重置(喚醒所有), False=自動重置(喚醒單一)
  lpTimerName: PWideChar                   // 具名支援跨進程
): THandle; stdcall;

function SetWaitableTimer(
  hTimer: THandle;                         // CreateWaitableTimer 返回句柄
  var lpDueTime: TLargeInteger;            // 起始時間 (Int64): 0=立即, <0=相對, >0=絕對 UTC FILETIME
  lPeriod: Longint;                        // 週期 (毫秒): 0=單次, >0=週期觸發
  pfnCompletionRoutine: TFNTimerAPCRoutine;// APC 回調函數指標 (可 nil)
  lpArgToCompletionRoutine: Pointer;       // 傳遞給 APC 回調的用戶指標
  fResume: BOOL                            // True=系統休眠/待機時也喚醒執行
): BOOL; stdcall;

關鍵參數深度解析

  1. bManualReset:
    • True:定時器觸發後保持**有信號狀態**,直到手動 CancelWaitableTimer,所有等待線程**全部**被喚醒。
    • False:定時器觸發後**自動重置為無信號**,僅喚醒**一個**等待線程 (類似 Semaphore)。
  2. lpDueTime (起始時間):三種模式 (詳見下篇教學)。
  3. lPeriod (週期):毫秒單位。0 = 單次觸發;>0 = 週期性觸發。
  4. APC 回調:第 4、5 參數配合 SleepEx 實現非阻塞高精度回調 (詳見後續教學)。
  5. fResume:True 時甚至能喚醒休眠/待機系統執行任務 (極強權限)。

範例一:單次觸發喚醒多線程 (bManualReset=True)

unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm)
  Button1: TButton;
  procedure Button1Click(Sender: TObject);
  procedure FormDestroy(Sender: TObject);
end;
var Form1: TForm1;
implementation {$R *.dfm}

var f: Integer; hWaitableTimer: THandle;

function MyThreadFun(p: Pointer): DWORD; stdcall;
var i, y: Integer;
begin
  Inc(f); y := 20 * f;
  { 等待定時器觸發 }
  if WaitForSingleObject(hWaitableTimer, INFINITE) = WAIT_OBJECT_0 then
    for i := 0 to 1000 do
    begin
      Form1.Canvas.Lock; Form1.Canvas.TextOut(20, y, IntToStr(i)); Form1.Canvas.Unlock;
      Sleep(1);
    end;
  Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var ThreadID: DWORD; DueTime: Int64;
begin
  hWaitableTimer := CreateWaitableTimer(nil, True, nil);  // 手動重置:喚醒所有
  DueTime := 0;  // 立即觸發
  SetWaitableTimer(hWaitableTimer, DueTime, 0, nil, nil, False);  // 單次觸發
  Repaint; f := 0;
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  CloseHandle(hWaitableTimer);
end;
end.

範例二:週期觸發單線程 (bManualReset=False, Period=500ms)

function MyThreadFun(p: Pointer): DWORD; stdcall;
var i, y: Integer;
begin
  Inc(f); y := 20 * f;
  { 將等待放入迴圈,每次週期觸發執行一次繪製 }
  for i := 0 to 1000 do
  begin
    if WaitForSingleObject(hWaitableTimer, INFINITE) = WAIT_OBJECT_0 then
    begin
      Form1.Canvas.Lock; Form1.Canvas.TextOut(20, y, IntToStr(i)); Form1.Canvas.Unlock;
    end;
  end;
  Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var ThreadID: DWORD; DueTime: Int64;
begin
  hWaitableTimer := CreateWaitableTimer(nil, False, nil);  // 自動重置:單一喚醒
  DueTime := 0;
  SetWaitableTimer(hWaitableTimer, DueTime, 500, nil, nil, False);  // 每 500ms 觸發
  Repaint; f := 0;
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
end;

執行效果對比

單次觸發:三線程同時啟動並行輸出

週期觸發:三線程輪流每 0.5 秒輸出一行

DFM 定義 (兩例共用)

object Form1: TForm1
  object Button1: TButton OnClick = Button1Click
end

WaitableTimer vs 其他同步物件

物件核心能力定時功能喚醒模式
Event訊號通知無手動/自動重置
Mutex互斥存取無擁有權轉移
Semaphore計數同步無計數遞減/釋放
WaitableTimer定時 + 同步高精度 (100ns)手動/自動重置 + 週期

實務選擇指南

  • 單純線程同步 → Event / Mutex / CriticalSection (更輕量)。
  • 需**定時觸發**同步 → WaitableTimer (唯一原生選擇)。
  • 需**高精度週期任務** → WaitableTimer + APC 回調 (非阻塞)。
  • 需**跨進程**定時同步 → 具名 CreateWaitableTimer。

下一步學習路徑

  1. 起始時間參數 DueTime 三模式詳解 (相對/絕對/零值)。
  2. APC 回調函數機制與 SleepEx 可喚醒等待。
  3. 工作線程非阻塞模式與指標參數傳遞。
  4. CancelWaitableTimer 動態控制。

WaitableTimer 是 Windows 同步物件中功能最豐富、精度最高的定時同步原語,掌握其參數組合可解決大多數定時協調難題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved