標準 TTimer 依賴 Windows 訊息隊列(WM_TIMER),精度約 10~15ms,且在 UI 忙碌時會丟失/延遲。timeSetEvent (winmm.lib) 由系統專用執行緒在內核級觸發回調,**精度可達 1ms**,適合音訊播放、數據採集、遊戲迴路等硬實時場景。
#ifndef Unit1H
#define Unit1H
#include
#include
#include
#include
#include // 關鍵頭文件
class TForm1 : public TForm {
__published:
TButton *BtnStart;
TLabel *LblTime;
void __fastcall BtnStartClick(TObject *Sender);
void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose);
private:
static void CALLBACK TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
UINT TimerID;
public:
__fastcall TForm1(TComponent* Owner);
};
extern PACKAGE TForm1 *Form1;
#endif
#include
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
TimerID = 0;
}
void CALLBACK TForm1::TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) {
// 注意:此回調運行在系統定時器執行緒,**不可直接操作 VCL 控件**
// 必須用 PostMessage / Synchronize / TThread::Queue 轉發到主執行緒
PostMessage(Form1->Handle, WM_USER + 1, 0, 0); // 自定義訊息通知主執行緒更新 UI
}
void __fastcall TForm1::BtnStartClick(TObject *Sender) {
// 週期 1000ms,回調函數,用戶數據 0,週期性+函數回調模式
TimerID = timeSetEvent(1000, 0, (LPTIMECALLBACK)TimerProc, 0,
TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
if (TimerID == 0) ShowMessage("創建失敗,請檢查 winmm.lib 是否鏈接");
}
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose) {
if (TimerID != 0) {
timeKillEvent(TimerID); // 必須釋放,否則資源洩漏
TimerID = 0;
}
}
// 在表單類中添加訊息處理更新 UI
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_USER + 1, TMessage, OnTimerUpdate)
END_MESSAGE_MAP(TForm)
void __fastcall TForm1::OnTimerUpdate(TMessage &Msg) {
LblTime->Caption = TimeToStr(Now()); // 安全更新 UI
}
$(BDSLIB)\win32\release 或直接在代碼 #pragma comment(lib, "winmm.lib")。#include 。CALLBACK (即 __stdcall),參數固定 5 個 DWORD。| 需求 | 實現方式 |
|---|---|
| 亞毫秒精度 (1ms) | timeBeginPeriod(1) 提升系統定時器分辨率,結束時 timeEndPeriod(1) |
| 單次觸發 | flags = TIME_ONESHOT | TIME_CALLBACK_FUNCTION |
| 回調傳遞上下文 | dwUser 傳 this 指針,回調中 static_cast |
| 高頻回調中做耗時運算 | **嚴禁**!回調必須極快返回,耗時任務 PostMessage 到工作執行緒/佇列 |
| 多媒體定時器 vs Waitable Timer | 後者 (CreateWaitableTimer) 精度更高、可關聯 I/O 完成埠,適合更復雜同步場景 |
timeSetEvent + PostMessage 組合是 BCB/VCL 中實現高精度週期性任務的標準模式:定時器執行緒只負責「打招呼」,主執行緒負責「幹活」,既保證精度又保證 VCL 線程安全。