可等待定时器(Win32, C++)

文章介绍了C++中的CWaitableTimer类,用于在Windows平台上创建、管理定时器,支持设置回调函数并控制定时触发。实例展示了如何使用这个类进行定时任务的调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CWaitableTimer.h

#pragma once
#include <string>
#include <functional>
#include <atomic>
#include <windows.h>

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

class CWaitableTimer
{
public:

    CWaitableTimer();
    ~CWaitableTimer();
    CWaitableTimer(const CWaitableTimer& r) = delete;
    CWaitableTimer& operator = (const CWaitableTimer& r) = delete;

    //
    // @brief: 创建定时器
    // @param: strName                  定时器名称
    // @ret: bool                       操作成功与否
    bool Create(const _tstring& strName);

    //
    // @brief: 打开定时器
    // @param: strName                  定时器名称
    // @ret: bool                       操作成功与否
    bool Open(const _tstring& strName);

    //
    // @brief: 设置完成例程回调
    // @param: cb                       例程回调
    // @param: dwStartMilliseconds      首次触发间隔时间(毫秒)
    // @param: dwPeriodMilliseconds     后续触发间隔时间(毫秒), 如果为零,则计时器将只发出一次信号
    // @ret: bool       操作成功与否
    bool SetCompletionRoutine(std::function<void(void)> cb, DWORD dwStartMilliseconds, DWORD dwPeriodMilliseconds);

    //
    // @brief: 关闭定时器
    // @param: void
    // @ret: void
    void Close();

private:

    HANDLE m_hTimer;                            //计时器句柄
    std::function<void(void)> m_cb;             //回调函数
    std::atomic<bool> m_bQuit;                  //退出标志
};

CWaitableTimer.cpp

#include "CWaitableTimer.h"
#include <future>
#include <thread>

CWaitableTimer::CWaitableTimer()
    :
    m_hTimer(NULL),
    m_bQuit(false)
{

}

CWaitableTimer::~CWaitableTimer()
{
    this->Close();
}

bool CWaitableTimer::Create(const _tstring& strName)
{
    if (m_hTimer)
    {
        return true;
    }

    SECURITY_ATTRIBUTES sa = { 0 };
    SECURITY_DESCRIPTOR sd = { 0 };

    sa.nLength = sizeof(sa);
    sa.bInheritHandle = FALSE;
    sa.lpSecurityDescriptor = &sd;

    //设置权限, 防止低权限进程不能打开
    (void)::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
    (void)::SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);

    m_hTimer = ::CreateWaitableTimer(&sa, false, strName.c_str());
    return NULL != m_hTimer;
}

bool CWaitableTimer::Open(const _tstring& strName)
{
    if (m_hTimer)
    {
        return true;
    }

    m_hTimer = ::OpenWaitableTimer(TIMER_ALL_ACCESS, false, strName.c_str());
    return NULL != m_hTimer;
}

bool CWaitableTimer::SetCompletionRoutine(std::function<void(void)> cb, DWORD dwBeginTime, DWORD dwPeriodTime)
{
    if (NULL == m_hTimer)
    {
        return false;
    }

    m_cb = cb;

    std::promise<bool> promiseValue;
    std::future<bool> futureValue = promiseValue.get_future();

    //创建定时器任务线程
    m_bQuit = false;

    std::thread([this, &promiseValue, dwBeginTime, dwPeriodTime]()
        {
            //正值表示绝对时间, 负值表示相对时间
            LARGE_INTEGER DueTime = { 0 };
            DueTime.QuadPart = 0 - (dwBeginTime * 10000LL);

            BOOL bRes = ::SetWaitableTimer(m_hTimer, &DueTime, dwPeriodTime, nullptr, this, false);
            promiseValue.set_value(bRes);

            while (!m_bQuit)
            {
                //等待定时器信号
                DWORD dwRet = ::WaitForSingleObject(m_hTimer, INFINITE);
                if (WAIT_OBJECT_0 == dwRet)
                {
                    if (m_cb)
                    {
                        m_cb();
                    }
                }
                else
                {
                    break;
                }

                //单次定时器则执行一次后退出等待逻辑
                if (0 == dwPeriodTime)
                {
                    break;
                }
            }
            m_bQuit = false;
        }
    ).detach();

    bool bRes = futureValue.get();
    return bRes;
}

void CWaitableTimer::Close()
{
    m_bQuit = true;

    if (NULL != m_hTimer)
    {
        //立即触发定时器, 让任务线程退出
        LARGE_INTEGER DueTime = { 0 };
        (void)::SetWaitableTimer(m_hTimer, &DueTime, 0, nullptr, this, false);

        //将计时器设置为非活动状态
        ::CancelWaitableTimer(m_hTimer);

        ::CloseHandle(m_hTimer);
        m_hTimer = NULL;
    }
}

main.cpp


#include <tchar.h>
#include <windows.h>
#include "Win32Utils/CTimeUtils.h"
#include "Win32Utils/CWaitableTimer.h"

int _tmain(int argc, LPCTSTR argv[])
{
    setlocale(LC_ALL, "");

    CWaitableTimer obj;
    obj.Create(_T("test"));
    
    obj.SetCompletionRoutine([&obj]() {
        _tprintf(_T("%s\r\n"), CTimeUtils::GetCurrentTimeString(false).c_str());

        }
    , 1000, 500);

    system("pause");

    return 0;
}

e119ab8bfe7446e79f8eb096ca2613e7.png

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值