封装多媒体定时器类和时间核心对象线程类

发布时间:2016-12-8 0:18:59 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"封装多媒体定时器类和时间核心对象线程类",主要涉及到封装多媒体定时器类和时间核心对象线程类方面的内容,对于封装多媒体定时器类和时间核心对象线程类感兴趣的同学可以参考一下。

背景:虽然Win95下可视化开发工具如VC、Delphi、C++   Builder等都有专用的定时器控件Timer,而且使用很方便,可以实现一定的定时功能,但最小计时精度仅为55ms,且定时器消息在多任务操作系统中的优先级很低,不能得到及时响应,往往不能满足实时控制环境下的应用。不过Microsoft公司在Win32   API函数库中已经为用户提供了一组用于高精度计时的底层函数,如果用户使用得当,计时精度可到1ms。这个计时精度、对于一般的实时系统控制完全可以满足要求。 在最近的工作中用到计时器的地方比较多,个人尝试了很多中定时器的实现,用于OnTimer定时不能满足要求,于是根据网上的资料封装了两类计时器,供大家参考。因为自己也是初学者,有问题的话请大家给出指导,下面是我封装的两种计时器的类。多媒体定时器类:/* *作者: FreeBird *描述:多媒体定时器 *完成时间:2013/7/14 *使用方法:重载函数Run * 1.先调用SetTimerResolution设置分辨率 * 2.调用SetEventType设置事件类型 * 3.调用GetTimerDelay时间周期 * 以上1到3不设置默认:m_nType = TIME_PERIODIC;m_nDelay = 3000;m_nResolution = 1; * 4.创建定时器CreateTimer * 5.用完后销毁定时器DestroyTimer */ #pragma once #include <MMSystem.h> #pragma comment(lib, "Winmm.lib") class MultimediaTimer { public: MultimediaTimer(void); virtual ~MultimediaTimer(void); public: //创建多媒体定时器 int CreateTimer(); //销毁对媒体定时器 int DestroyTimer(); //设置分辨率,最小精度1ms,如果设置的超出机器支持的范围,则按照min(机器支持的最小值,1)来设置 int SetTimerResolution(int nResolution); //获取调用者自己设定的分辨率 int GetTimerResolution() const; //设置以毫秒指定事件的周期 int SetTimerDelay(int nDelay); //获取定时器时间周期 int GetTimerDelay() const; //设置定时器事件类型 void SetEventType(int nEventType); //获取定时器事件类型 int GetEventType() const; //多媒体定时器回调函数 static void CALLBACK TimerCallBackPro(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2); public: //子类重载该函数实现不同定时功能 virtual void Run(); private: //获得系统支持的计时器装置驱动所支援的最小的解析度值(延时的精度),返回设置的分辨率,返回负数表示失败 int GetSystemPeriod(int &nPeriodMix, int &nPeriodMax); private: //计时器的精度,默认设置机器支持的最小精度,一般是1ms MMRESULT m_nTimerID; //分辨率 int m_nResolution; //以毫秒指定事件的周期 int m_nDelay; //设置定时器事件类型 int m_nType; //定时器事件类型 enum eEventType { RunOnce = TIME_ONESHOT, //uDelay毫秒后只产生一次事件 RunCycle = TIME_PERIODIC //每隔uDelay毫秒周期性地产生事件。 }; };#include "StdAfx.h" #include "MultimediaTimer.h" #ifdef _DEBUG #define new DEBUG_NEW #endif MultimediaTimer::MultimediaTimer(void) { m_nTimerID = 0; m_nType = TIME_PERIODIC; m_nDelay = 1000; m_nResolution = 1; } MultimediaTimer::~MultimediaTimer(void) { } int MultimediaTimer::CreateTimer() { if ( timeBeginPeriod(m_nResolution) != TIMERR_NOERROR ) return -1; m_nTimerID = timeSetEvent(m_nDelay, m_nResolution, (LPTIMECALLBACK)TimerCallBackPro, (DWORD)this, m_nType); if ( m_nTimerID == 0) { timeEndPeriod(m_nResolution); return -2; } return 0; } int MultimediaTimer::DestroyTimer() { if ( m_nTimerID ) { timeKillEvent(m_nTimerID); timeEndPeriod(m_nResolution); m_nTimerID = 0; } return 0; } int MultimediaTimer::SetTimerResolution( int nResolution ) { int nPeriodMin; //系统支持的最小值 int nPeriodMax; //系统支持的最大值 //获得机器支持的分辨路范围 if ( GetSystemPeriod(nPeriodMin, nPeriodMax) != 0 ) return -1; //如果超出机器支持范围按照min(机器支持的最小值,1)来设置 if ( nResolution < nPeriodMin || nResolution > nPeriodMax ) { m_nResolution = min( max(nPeriodMin, 1), nPeriodMax ); } else { m_nResolution = nResolution; } return 0; } int MultimediaTimer::GetTimerResolution() const { return m_nResolution; } int MultimediaTimer::GetSystemPeriod(int &nPeriodMix, int &nPeriodMax) { TIMECAPS tc; //向机器申请一个多媒体定时器 if ( timeGetDevCaps(&tc,sizeof(TIMECAPS)) != TIMERR_NOERROR ) return -1; nPeriodMix = tc.wPeriodMin; nPeriodMax = tc.wPeriodMax; return 0; } int MultimediaTimer::SetTimerDelay(int nDelay) { m_nDelay = nDelay; return 0; } int MultimediaTimer::GetTimerDelay() const { return m_nDelay; } void MultimediaTimer::Run() { } void MultimediaTimer::TimerCallBackPro(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2) { MultimediaTimer *pMulTime = (MultimediaTimer *)dwUser; pMulTime->Run(); } void MultimediaTimer::SetEventType(int nEventType) { m_nType = nEventType; } int MultimediaTimer::GetEventType() const { return m_nType; }用线程实现的时间核心对象类:#include <winbase.h> //包含了Windows平台专属的一些函数和宏的定义 #include <windows.h> #include <process.h> //一般用程序获得进程列表时会用这个文件中的API class TimerThread { protected: HANDLE _TerminateEvent; //事件句柄 HANDLE _TimerHandle; //时间内核对象 HANDLE _hHandle; //线程句柄 unsigned _ThreadID; //线程ID HWND _hNotifyWnd; // 通知窗口 LONG _TimerHandleCount; //时间内核对象调用次数 LONG _lPeriodTime; //定时器周期 SYSTEMTIME _st; //指定开始执行时间 int _lSecond; //指定多少秒后开始执行 CRITICAL_SECTION _Mutex; //临界区 protected: virtual void OnInit(); //初始化,子类需要重载的函数 virtual void OnTimer()=0; //定时器函数,子类必须重载的函数 virtual void OnExit(); //退出,子类需要重载的函数 static UINT WINAPI StaticThreadProc(LPVOID lpPara); virtual void Run(); //运行 public: TimerThread(int nPriority = THREAD_PRIORITY_NORMAL); //构造函数中创建事件对象、时间内核对象、初始化临界区并启动线程 virtual ~TimerThread(); BOOL SetTimer(LONG lPeriodTime); //设置定时器,周期执行ms,该函数调用后立即按周期执行 BOOL SetTimer(SYSTEMTIME st, LONG lPeriodTime); //调用该函数后,在st指定时间到时,按照周期执行 BOOL SetTimer(int lSecond, LONG lPeriodTime); //调用该函数后,在指定lSecond秒后开始执行 void Terminate(); //终止定时器 HANDLE GetHandle(); //获取线程句柄 inline void SetWnd(HWND hWnd); //关联消息的窗口句柄 LONG GetFinishedCount(); //获取线程被执行次数 }; void TimerThread::SetWnd(HWND hWnd) //关联消息的窗口句柄 { // assert(::IsWindow(hWnd)); _hNotifyWnd = hWnd; } #endif _TIMER_THREAD_H_ /* 作者:FreeBird 功能:时间核心对象线程类,该类是抽象类,需要子类实现OnTimer函数,实现定时器的功能 */ #ifndef _TIMER_THREAD_H_ #define _TIMER_THREAD_H_ #include <objbase.h> //主持COM的一个头文件 #include "TimerThread.h" TimerThread::TimerThread(int nPriority) { _TimerHandleCount = 0; _TerminateEvent = CreateEvent(0, TRUE, FALSE, NULL); //创建线程 _TimerHandle = CreateWaitableTimer(NULL, FALSE, NULL); //创建时间核心对象,自动重置定时器 ::InitializeCriticalSection(&_Mutex); //初始化临界区 unsigned int id; _hHandle = (HANDLE)_beginthreadex(NULL, 0, StaticThreadProc, this, 0, &id); _ThreadID = id; if(_hHandle != NULL) SetThreadPriority(_hHandle, nPriority); //设置线程优先级 //else // MessageBox(NULL, "Create thread fail!", "TimerThread", MB_OK); } TimerThread::~TimerThread() { Terminate(); CloseHandle(_hHandle); CloseHandle(_TimerHandle); CloseHandle(_TerminateEvent); ::DeleteCriticalSection(&_Mutex); } //子类需要重载的函数 void TimerThread::OnInit() { } //OnTimer()函数需要在子类实现 //子类需要重载的函数 void TimerThread::OnExit() { } BOOL TimerThread::SetTimer(LONG lPeriodTime)//ms { _lPeriodTime = lPeriodTime; LARGE_INTEGER liUTC; memset(&liUTC, 0, sizeof(LARGE_INTEGER)); return SetWaitableTimer(_TimerHandle, &liUTC, _lPeriodTime, NULL, NULL, FALSE)!=0; } BOOL TimerThread::SetTimer(SYSTEMTIME st, LONG lPeriodTime)//ms { _lPeriodTime = lPeriodTime; _st = st; //SYSTEMTIME结构,用来设置第1次通知的时间 FILETIME ftLocal, ftUTC; //FILETIME结构,用来接受STSTEMTIME结构的转换 LARGE_INTEGER liUTC; //LARGE_INTEGER结构,作为SetWaitableTimer的参数,定时时间 SystemTimeToFileTime(&_st, &ftLocal); //将SYSTIME结构转换为FILETIME结构 LocalFileTimeToFileTime(&ftLocal, &ftUTC); //将本地时间转换为标准时间(UTC),SetWaitableTimer函数接受一个标准时间 liUTC.LowPart = ftUTC.dwLowDateTime; // 设置LARGE_INTEGER结构,因为该结构数据要作为SetWaitableTimer的参数 liUTC.HighPart = ftUTC.dwHighDateTime; return SetWaitableTimer(_TimerHandle, &liUTC, _lPeriodTime, NULL, NULL, FALSE) != 0; } BOOL TimerThread::SetTimer(int lSecond, LONG lPeriodTime) { _lSecond = lSecond; _lPeriodTime = lPeriodTime; LARGE_INTEGER li; const int nTimerUnitsPerSecond = 1000000000 / 100; //每1s中有多少个100ns li.QuadPart = -(_lSecond * nTimerUnitsPerSecond ); //负数,表示相对值lSecond秒 return SetWaitableTimer(_TimerHandle, &li, _lPeriodTime, NULL, NULL, FALSE)!=0; } void TimerThread::Terminate() { SetEvent(_TerminateEvent); if(WaitForSingleObject(_hHandle, 200) != WAIT_OBJECT_0) TerminateThread(_hHandle, 0); } void TimerThread::Run() { HANDLE HandleArray[2]; HandleArray[0] = _TimerHandle; HandleArray[1] = _TerminateEvent; for(;;) { DWORD ret = WaitForMultipleObjects(2, HandleArray, false, INFINITE); //当其中有一个信号量是往下执行 if(ret == WAIT_OBJECT_0 + 1) //第二个事件发生 break; if(ret == WAIT_OBJECT_0) //第一个事件发生 { try { OnTimer(); } catch (...) { } InterlockedIncrement(&_TimerHandleCount); //共享变量,互斥锁,时间内核对象被调用次数 } } } HANDLE TimerThread::GetHandle() { return _hHandle; } LONG TimerThread::GetFinishedCount() { return _TimerHandleCount; } UINT WINAPI TimerThread::StaticThreadProc(LPVOID lpPara) { TimerThread *pObj = (TimerThread*)lpPara; pObj->OnInit(); pObj->Run(); pObj->OnExit(); return 0; }

上一篇:深入分析HBase Compaction机制
下一篇:JAVA net之TCP

相关文章

相关评论