【问题标题】:Timer in a win32 servicewin32服务中的定时器
【发布时间】:2008-10-22 00:17:35
【问题描述】:

有人可以告诉我在 Win32 服务中设置计时器的最简单方法吗?

我想我可以为此创建一个虚拟窗口,或者让第二个线程进行滴答计数,但最好的方法是什么?有没有更优雅的方式?

提前致谢。

【问题讨论】:

    标签: c++ windows winapi windows-services


    【解决方案1】:

    您可以使用计时器队列 (http://msdn.microsoft.com/en-us/library/ms686796.aspx)。它们不需要 HWND。

    【讨论】:

    • 这听起来很有趣,请提供一个例子
    【解决方案2】:

    除了使用 UI 计时器(即使您可以使用 1800-INFO 先生所示的 NULL 窗口句柄),您还可以使用内核可等待计时器对象。请参阅 API 文档中的 CreateWaitableTimer。然后可以使用 WaitForSingleObject 或 WaitForMultipleObjects 等来等待这些,如果这已经是您的服务等待外部事件的方式,这将特别有用。

    如果从第一个链接中不清楚,SetWaitableTimer 函数可以将完成例程(用户回调)与计时器相关联。请记住使用...Ex 版本的 WaitForMultipleObjects(等),以便线程处于“可提醒”状态。

    【讨论】:

    • 听起来不错 - 我选择了计时器队列,但我也会阅读您的链接。谢谢!
    • 谢谢,我认为 TimerQueues 可能有点矫枉过正,但这实际上取决于您的服务的其余部分是如何设计的。如果您想要一个 ThreadPool 线程来处理计时器事件,TimerQueues 会很棒。如果您已经有一个 WFMO 或 GetMessage 循环,那么您可以使用其他选项。
    【解决方案3】:

    您可以发送主线程 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

    【讨论】:

    • 谢谢 - 不幸的是我没有消息循环:)
    • 所以创建一个!调用 ::GetMessage 或 ::PeekMessage 后,消息队列由操作系统设置。
    【解决方案4】:

    您可以使用 SetTimer 设置计时器,然后在消息循环中捕获 WM_TIMER 消息。

    例子:

    // 设置一个10秒后过期的定时器

    SetTimer(hwnd,IDT_TIMER1, 10000,(TIMERPROC) NULL);

    ...然后在消息循环中:

    开关(wParam)

    { 
    
        case IDT_TIMER1: 
    
            // Boom goes the dynamite
    

    如果您不想进行消息循环处理,您还可以清除 TIMERPROC 类型的函数并在计时器到期时调用该函数。

    【讨论】:

    • +1 表示“轰轰烈烈”,但在你的格式上做一些工作
    • 谢谢 - 我的服务中没有消息循环来捕获消息:)
    • 所以创建一个!调用 ::GetMessage 或 ::PeekMessage 后,消息队列由操作系统设置。
    【解决方案5】:

    在您的一个 cmets 中,您说“...该服务正在处理其他线程中的内容,我只需要每秒检查几个文件的状态。”

    轮询不是检查文件状态的最佳方式,并且会对系统性能产生不利影响。虽然(有时)通过网络执行此操作会出现问题,但您应该查看 http://msdn.microsoft.com/en-us/library/aa364417(VS.85).aspxhttp://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx 了解如何执行此操作,并查看 http://blogs.msdn.com/oldnewthing/archive/2006/01/24/516808.aspx 了解您应该这样做的原因。

    【讨论】:

    • 好的,谢谢。我确实知道这些功能,您可能是对的,我应该更聪明并使用它们。由于我无法控制文件,我只能查看文件的大小,但公平地说,我不会连续轮询它(仅每秒一次)。
    【解决方案6】:

    你只是想时不时地“醒来”做一些工作吗?您可以随时使用 Sleep()。

    此外,我通常有一个线程在 while(1 == 1) 循环中,里面有一个睡眠。在那里我可以检查关闭请求和其他杂项家务。您可以使用该系统为应用程序中的工作线程触发事件或互斥锁。

    【讨论】:

    • 不,该服务正在处理其他线程中的东西,我只需要每秒检查几个文件的状态。
    • 可能对你来说有点矫枉过正,但是......你可以使用 ReadDirectoryChangesW 来“监听”文件的更改而不是轮询它们,它可能会更有效率,因为你只会在那里醒来是对流程的更改,而不是每个“x”毫秒……但设置起来更难。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    • 2010-10-18
    • 2010-09-20
    • 1970-01-01
    • 2014-09-02
    • 1970-01-01
    相关资源
    最近更新 更多