Win32 可等待定时器

CWaitableTimer.h

#pragma once
#include 
#include 
#include 
#include 

#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 cb, DWORD dwStartMilliseconds, DWORD dwPeriodMilliseconds);

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

private:

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

CWaitableTimer.cpp

#include "CWaitableTimer.h"
#include 
#include 

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 cb, DWORD dwBeginTime, DWORD dwPeriodTime)
{
    if (NULL == m_hTimer)
    {
        return false;
    }

    m_cb = cb;

    std::promise promiseValue;
    std::future 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 
#include 
#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;
}

Win32 可等待定时器_第1张图片

你可能感兴趣的:(C++,Win32,Win32,C++,定时器)