該定時器實現了線程之間的互鎖。使用時先初始化全局對象vector,設定好使用的定時器的個數,
#pragma once
#include "afxmt.h"
#include <vector>
using namespace std;
//定時器
typedef struct tagSPLCTimer
{
LONGLONG TimerStart;
LONGLONG TimerEnd;
double Time;
}SPLCTimer;
vector<SPLCTimer> g_PLC_Timer ;//全局變量,定時器集合
//定時器操作類
class CustomTimer
{
public:
CustomTimer();
~CustomTimer();
private:
//線程互斥用-定時器線程鎖
CCriticalSection m_PLCCritical_Timer_Mutix;
public:
//初始化定時器
void InitTimer(unsigned long TimerID, unsigned long bTime);
//獲取時鐘基準
LONGLONG GetClock();
//死循環時間
void SleepTime(double Time);//ms
//定時器是否結束
bool IsTimerEnd(unsigned long TimerID);
//獲取已經定時的時間
void GetUsedTime(unsigned long TimerID, unsigned long& bTime);
//清除定時器已經記的時間
void RstTimer(unsigned long TimerID);
public:
};
#include "pch.h"
#include "CustomTimer.h"
CustomTimer::CustomTimer()
{
}
CustomTimer::~CustomTimer()
{
}
void CustomTimer::InitTimer(unsigned long TimerID, unsigned long bTime)
{
double dfMinus, dfTim;
LARGE_INTEGER litmp;
LONGLONG dfFreq;
QueryPerformanceFrequency(&litmp);
dfFreq = litmp.QuadPart;
unsigned long nTimerSize = g_PLC_Timer.size();
if (TimerID < 0 || TimerID >= nTimerSize)
{
CString info;
info.Format(_T("索引定時器ID號(%d)的範圍不對"), TimerID);
AfxMessageBox(info, MB_TOPMOST);
return;
}
if (!IsTimerEnd(TimerID))
{
CString info;
info.Format(_T("索引定時器ID號(%d)+IsTimerEnd沒完成卻去InitTimer初始化"), TimerID);
AfxMessageBox(info, MB_TOPMOST);
}
m_PLCCritical_Timer_Mutix.Lock();//線程鎖
g_PLC_Timer[TimerID].TimerStart = GetClock();
g_PLC_Timer[TimerID].Time = bTime;
m_PLCCritical_Timer_Mutix.Unlock();//線程鎖
}
LONGLONG CustomTimer::GetClock()
{
LONGLONG time = 0;
LARGE_INTEGER litmp;
LONGLONG QPart1;
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart;
time = (LONGLONG)(QPart1);
return time;
}
void CustomTimer::SleepTime(double Time)
{
LARGE_INTEGER litmp;
LONGLONG QPart1, QPart2;;
double dfMinus = 0, dfFreq = 0, dfTim = 0;
double dfTgTime = 0;
QueryPerformanceFrequency(&litmp);//獲得機器內部定時器的時鐘頻率
dfFreq = (double)litmp.QuadPart;
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart;// 獲得初始值
dfTgTime = Time * 0.001;//轉化爲分鐘
while (dfTim < dfTgTime)
{
QueryPerformanceCounter(&litmp);
QPart2 = litmp.QuadPart;//獲得中止值
dfMinus = (double)(QPart2 - QPart1);
dfTim = dfMinus / dfFreq;
}
}
bool CustomTimer::IsTimerEnd(unsigned long TimerID)
{
double dfMinus, dfTim;
LARGE_INTEGER litmp;
LONGLONG dfFreq;
QueryPerformanceFrequency(&litmp);
dfFreq = litmp.QuadPart;
unsigned long nTimerSize = g_PLC_Timer.size();
if (TimerID < 0 || TimerID >= nTimerSize)
{
CString info;
info.Format(_T("索引定時器ID號(%d)的範圍不對"), TimerID);
AfxMessageBox(info, MB_TOPMOST);
return false;
}
m_PLCCritical_Timer_Mutix.Lock();//線程鎖
g_PLC_Timer[TimerID].TimerEnd = GetClock();
dfMinus = g_PLC_Timer[TimerID].TimerEnd - g_PLC_Timer[TimerID].TimerStart;
if (dfMinus < 0)
dfMinus = 0;
dfTim = (int)10000 * dfMinus / dfFreq;
dfTim /= 10.0;
bool Retn = false;
if (dfTim >= g_PLC_Timer[TimerID].Time) //必須是下一個週期到來
{
g_PLC_Timer[TimerID].TimerStart = 0;
g_PLC_Timer[TimerID].TimerEnd = 0;
g_PLC_Timer[TimerID].Time = 0;
Retn = true;
}
else
{
Retn = false;
}
m_PLCCritical_Timer_Mutix.Unlock(); //線程鎖
return Retn;
}
void CustomTimer::GetUsedTime(unsigned long TimerID, unsigned long & bTime)
{
LARGE_INTEGER litmp;
LONGLONG dfMinus, dfFreq, dfTim, tempdfTim;
QueryPerformanceFrequency(&litmp);
dfFreq = litmp.QuadPart;
unsigned long nTimerSize = g_PLC_Timer.size();
if (TimerID < 0 || TimerID >= nTimerSize)
{
CString info;
info.Format(_T("索引定時器ID號(%d)的範圍不對"), TimerID);
AfxMessageBox(info, MB_TOPMOST);
return;
}
m_PLCCritical_Timer_Mutix.Lock();//線程鎖
g_PLC_Timer[TimerID].TimerEnd = GetClock();
dfMinus = g_PLC_Timer[TimerID].TimerEnd - g_PLC_Timer[TimerID].TimerStart;
if (dfMinus < 0)//內存溢出
dfMinus += 0xffffffffffffffff;
tempdfTim = 1000 * dfMinus;
if (tempdfTim < 0)//內存溢出
tempdfTim += 0xffffffffffffffff;
dfTim = tempdfTim / dfFreq;
bool Retn = false;
if (dfTim >= g_PLC_Timer[TimerID].Time)
{
g_PLC_Timer[TimerID].TimerStart = 0;
g_PLC_Timer[TimerID].TimerEnd = 0;
g_PLC_Timer[TimerID].Time = 0;
bTime = 0;//輸出
}
else
{
bTime = (unsigned long)dfTim; //輸出
}
m_PLCCritical_Timer_Mutix.Unlock(); //線程鎖
}
void CustomTimer::RstTimer(unsigned long TimerID)
{
unsigned long nTimerSize = g_PLC_Timer.size();
if (TimerID < 0 || TimerID >= nTimerSize)
{
CString info;
info.Format(_T("索引定時器ID號(%d)的範圍不對"), TimerID);
AfxMessageBox(info, MB_TOPMOST);
return;
}
m_PLCCritical_Timer_Mutix.Lock(); //線程鎖
g_PLC_Timer[TimerID].TimerStart = 0;
g_PLC_Timer[TimerID].TimerEnd = 0;
g_PLC_Timer[TimerID].Time = 0;
m_PLCCritical_Timer_Mutix.Unlock(); //線程鎖
}