TTimer (WM_TIMER) 精度 ~55ms,優先級極低,訊息佇列擁塞時嚴重延遲。timeSetEvent) 精度 **1ms 級**,獨立執行緒回呼,適合即時控制、音訊同步、高頻採樣。
#include
#pragma comment(lib, "winmm.lib")
// 1. 取得系統啟動後毫秒數
DWORD timeGetTime(); // 回繞週期 ~49.7 天
// 2. 建立定時器事件
MMRESULT timeSetEvent(
UINT uDelay, // 週期 (ms)
UINT uResolution, // 解析度 (ms),越小越精確,建議 1
LPTIMECALLBACK lpTimeProc, // 回呼函式
DWORD dwUser, // 使用者資料傳遞給回呼
UINT fuEvent // TYPE: TIME_ONESHOT | TIME_PERIODIC
); // 成功返回 Timer ID,失敗返回 0
// 3. 刪除定時器
MMRESULT timeKillEvent(UINT uTimerID);
// 4. 回呼函式原型 (必須 __stdcall / CALLBACK)
void CALLBACK TimeProc(
UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2
);
回呼在**多媒體定時器執行緒**中執行,**只能呼叫極少量 API**:
PostMessage, timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEventmidiOutShortMsg, midiOutLongMsg, OutputDebugString**正確模式**:回呼僅 PostMessage(hwnd, WM_MY_TIMER, 0, 0) 通知主執行緒,主執行緒訊息迴路處理實際邏輯。
// Unit1.h
class TForm1 : public TForm {
__published:
TButton *BtnStart, *BtnStop;
TLabel *LblCount;
void __fastcall BtnStartClick(TObject* Sender);
void __fastcall BtnStopClick(TObject* Sender);
private:
UINT timerId;
static void CALLBACK TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD, DWORD);
void __fastcall HandleTimer(); // 主執行緒處理
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_USER+1, TMessage, OnTimerMsg)
END_MESSAGE_MAP(TForm)
public:
__fastcall TForm1(TComponent* Owner);
};
// Unit1.cpp
#define WM_TIMER_NOTIFY (WM_USER + 1)
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner), timerId(0) {}
void __fastcall TForm1::BtnStartClick(TObject* Sender) {
if (timerId) return;
timerId = timeSetEvent(10, 1, TimerProc, (DWORD)this, TIME_PERIODIC);
if (!timerId) ShowMessage("建立定時器失敗");
}
void __fastcall TForm1::BtnStopClick(TObject* Sender) {
if (timerId) { timeKillEvent(timerId); timerId = 0; }
}
void CALLBACK TForm1::TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD, DWORD) {
TForm1* self = (TForm1*)dwUser;
PostMessage(self->Handle, WM_TIMER_NOTIFY, 0, 0); // 唯一允許的 UI 互動
}
void __fastcall TForm1::OnTimerMsg(TMessage& Msg) {
HandleTimer(); // 主執行緒安全執行 UI/邏輯
}
void __fastcall TForm1::HandleTimer() {
static int count = 0;
LblCount->Caption = "Count: " + IntToStr(++count);
}
uResolution = 1 最高精度,但系統會更頻繁喚醒 CPU,增加功耗、減少電池壽命。timeKillEvent** 釋放資源。| 方案 | 精度 | 適用場景 | 備註 |
|---|---|---|---|
CreateTimerQueueTimer (Thread Pool) | ~1ms | 一般背景週期性任務 | Win2K+,自動執行緒池管理 |
SetWaitableTimer + WaitForSingleObject | ~0.5ms | 需精確喚醒的同步等待 | 可關聯非訊號狀態 |
QueryPerformanceCounter + 忙等待/睡眠修正 | 亞微秒 | 極高精度測量/同步 | CPU 佔用高,僅測量或極短間隔 |
C++20 std::chrono + std::jthread | ~ms | 跨平台現代代碼 | 配合 sleep_until 迴圈 |