【发布时间】:2008-10-22 00:17:35
【问题描述】:
有人可以告诉我在 Win32 服务中设置计时器的最简单方法吗?
我想我可以为此创建一个虚拟窗口,或者让第二个线程进行滴答计数,但最好的方法是什么?有没有更优雅的方式?
提前致谢。
【问题讨论】:
标签: c++ windows winapi windows-services
有人可以告诉我在 Win32 服务中设置计时器的最简单方法吗?
我想我可以为此创建一个虚拟窗口,或者让第二个线程进行滴答计数,但最好的方法是什么?有没有更优雅的方式?
提前致谢。
【问题讨论】:
标签: c++ windows winapi windows-services
您可以使用计时器队列 (http://msdn.microsoft.com/en-us/library/ms686796.aspx)。它们不需要 HWND。
【讨论】:
除了使用 UI 计时器(即使您可以使用 1800-INFO 先生所示的 NULL 窗口句柄),您还可以使用内核可等待计时器对象。请参阅 API 文档中的 CreateWaitableTimer。然后可以使用 WaitForSingleObject 或 WaitForMultipleObjects 等来等待这些,如果这已经是您的服务等待外部事件的方式,这将特别有用。
如果从第一个链接中不清楚,SetWaitableTimer 函数可以将完成例程(用户回调)与计时器相关联。请记住使用...Ex 版本的 WaitForMultipleObjects(等),以便线程处于“可提醒”状态。
【讨论】:
您可以发送主线程 WM_TIMER 消息。消息的 lParam 是回调函数的地址,或者您可以将其保留为 NULL 并在消息泵中自行处理。
在本例中,我们将计时器发送到线程消息泵,不需要与计时器关联的窗口。
UINT timer;
VOID CALLBACK Timer(HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
)
{
KillTimer(0, timer);
}
timer=SetTimer(0, // window handle
0, // id of the timer message, leave 0 in this case
10000, // millis
Timer // callback
);
// pump messages
while (GetMessage) etc...
Timer 回调将由 DispatchMessage 调用。这个问题让我想起了最近的ONT。
【讨论】:
您可以使用 SetTimer 设置计时器,然后在消息循环中捕获 WM_TIMER 消息。
例子:
// 设置一个10秒后过期的定时器
SetTimer(hwnd,IDT_TIMER1, 10000,(TIMERPROC) NULL);
...然后在消息循环中:
开关(wParam)
{
case IDT_TIMER1:
// Boom goes the dynamite
如果您不想进行消息循环处理,您还可以清除 TIMERPROC 类型的函数并在计时器到期时调用该函数。
【讨论】:
在您的一个 cmets 中,您说“...该服务正在处理其他线程中的内容,我只需要每秒检查几个文件的状态。”
轮询不是检查文件状态的最佳方式,并且会对系统性能产生不利影响。虽然(有时)通过网络执行此操作会出现问题,但您应该查看 http://msdn.microsoft.com/en-us/library/aa364417(VS.85).aspx 或 http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx 了解如何执行此操作,并查看 http://blogs.msdn.com/oldnewthing/archive/2006/01/24/516808.aspx 了解您应该这样做的原因。
【讨论】:
你只是想时不时地“醒来”做一些工作吗?您可以随时使用 Sleep()。
此外,我通常有一个线程在 while(1 == 1) 循环中,里面有一个睡眠。在那里我可以检查关闭请求和其他杂项家务。您可以使用该系统为应用程序中的工作线程触发事件或互斥锁。
【讨论】: