这就是我要完成的任务。我有一个外部设备,需要在特定间隔内收到消息。间隔取决于情况而变化。我预计我不会需要超过100Hz(10ms)的消息速率。
当然,我可以实现自旋循环,但我希望有一种解决方案,不需要浪费太多资源。
提供的问题/答案链接并未解决此问题。虽然我同意这个问题已经以几种不同的方式被问过了,但还没有一个好的解决方案来解决这个问题。
提供的大多数答案都涉及使用Stopwatch并手动执行定时任务,这完全太消耗CPU了。唯一可行的解决方案是使用多媒体定时器,但像Haans所提到的那样存在一些缺陷。我已经找到另一个解决方案,在下面添加。我目前不知道其中的缺陷,但我打算进行一些测试和研究。我仍然对这个解决方案的评论感兴趣。
WINAPI调用方式:
BOOL WINAPI CreateTimerQueueTimer(
_Out_ PHANDLE phNewTimer,
_In_opt_ HANDLE TimerQueue,
_In_ WAITORTIMERCALLBACK Callback,
_In_opt_ PVOID Parameter,
_In_ DWORD DueTime,
_In_ DWORD Period,
_In_ ULONG Flags
);
并且
BOOL WINAPI DeleteTimerQueueTimer(
_In_opt_ HANDLE TimerQueue,
_In_ HANDLE Timer,
_In_opt_ HANDLE CompletionEvent
);
链接 - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682485%28v=vs.85%29.aspx
我正在使用PInvoke来完成这项工作。当处理多媒体定时器时,也需要使用它。
对于那些感兴趣的人,我的PInvoke签名如下。 Pinvoke链接
[DllImport("kernel32.dll")]
static extern bool CreateTimerQueueTimer(out IntPtr phNewTimer,
IntPtr TimerQueue, WaitOrTimerDelegate Callback, IntPtr Parameter,
uint DueTime, uint Period, uint Flags);
// This is the callback delegate to use.
public delegate void WaitOrTimerDelegate (IntPtr lpParameter, bool TimerOrWaitFired);
[DllImport("kernel32.dll")]
static extern bool DeleteTimerQueueTimer(IntPtr TimerQueue, IntPtr Timer,
IntPtr CompletionEvent);
使用CreateTimerQueueTimer启动计时器回调。使用DeleteTimerQueueTimer停止计时器回调。您还可以创建自定义队列,使其更具灵活性。然而,如果只需要单个实例,则最简单的实现方法是使用默认队列。
我测试了这个解决方案和一个使用带有自旋循环的Stopwatch的解决方案,结果表明它们在时间上几乎相同。然而,在我的机器上CPU负载显著不同。
使用自旋循环的Stopwatch- ~12-15%的恒定CPU负载(大约占用了一个核心的50%)
CreateTimerQueueTimer- ~3-4%的恒定CPU负载
我也觉得使用CreateTimerQueueTimer选项将减少代码维护,因为它不需要添加逻辑到您的代码流程中。