TTimer 精度約 10-15 ms(受訊息佇列影響),且最小間隔受限於系統時鐘節拍。timeSetEvent) 可達 **1 ms** 級精度,在獨立執行緒回調,適合音訊、採集、控制迴路。MMRESULT timeSetEvent(
UINT uDelay, // 週期 (ms)
UINT uResolution, // 解析度 (0=系統預設)
LPTIMECALLBACK lpCallback, // 回調函數
DWORD dwUser, // 使用者資料
UINT fuEvent // 旗標
);
void timeKillEvent(MMRESULT uTimerID);
常用旗標:TIME_PERIODIC (週期性) | TIME_CALLBACK_FUNCTION (函數回調)。
#ifndef Unit1H
#define Unit1H
#include
#include
#include
#include
class TForm1 : public TForm {
__published:
TButton *Button1;
TLabel *Label1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose);
private:
public:
__fastcall TForm1(TComponent* Owner);
static void CALLBACK TimeProc(UINT uID, UINT uMsg,
DWORD dwUser, DWORD dw1, DWORD dw2);
MMRESULT TimerID;
};
extern PACKAGE TForm1 *Form1;
#endif
#include
#include
#pragma hdrstop
#include "Unit1.h"
#pragma comment(lib, "winmm.lib")
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
TimerID = 0;
}
void CALLBACK TForm1::TimeProc(UINT, UINT, DWORD, DWORD, DWORD) {
// 注意:回調在獨立執行緒,直接操作 VCL 控件不安全!
// 這裡僅為示範,實務請用 PostMessage/Synchronize/佇列傳遞主執行緒
Form1->Label1->Caption = FormatDateTime("hh:nn:ss.zzz", Now());
}
void __fastcall TForm1::Button1Click(TObject *Sender) {
TimerID = timeSetEvent(1000, 0, (LPTIMECALLBACK)TimeProc, 0,
TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
if (TimerID == 0) ShowMessage("建立定時器失敗");
}
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose) {
if (TimerID) { timeKillEvent(TimerID); TimerID = 0; }
}
| 方法 | 適用場景 | 代碼片段 |
|---|---|---|
| PostMessage | 簡單通知、低頻 | PostMessage(Handle, WM_USER+1, 0, 0); → 主執行緒 WndProc 處理 |
| TThread::Synchronize | 需執行複雜 VCL 邏輯 | Synchronize([&]{ Label1->Caption = ...; }); (C++11 Lambda) |
| 無鎖佇列 + Timer 輪詢 | 高頻資料流 (音訊/感測器) | 回調 queue.push(data);主執行緒 Timer while(queue.pop(d)) updateUI(d); |
timeBeginPeriod(1):將系統時鐘解析度提升至 1 ms(配合 timeEndPeriod 成對使用)。QueryPerformanceCounter) + 忙等待或多媒體定時器 TIME_KILL_SYNCHRONOUS 旗標(Vista+)。timeKillEvent → 定時器洩漏,卸載 DLL 時崩潰。timeBeginPeriod。timeSetEvent 是 Windows 多媒體定時器的經典入口,配合正確的跨執行緒 UI 更新模式,能滿足多數毫秒級定時需求。現代專案若需更高精度或跨平台,建議改用 C++11 std::chrono + std::thread 或 Boost.Asio steady_timer。