之前寫了一個C++的控制臺程式,每月3號、13號、23號的8點定時從SQLServer資料庫中,分別獲取上月下旬、本月上旬、本月中旬的站點資料,然后根據對應的時間區間生成XML資料,我使用的是C++ Boost庫作為定時器,代碼如下:
// 頭檔案
#pragma once
#include <boost/asio/deadline_timer.hpp>
#include <boost/thread/thread.hpp>
#include "my_log.h"
class XmlFileGenerateTimer : public my_log
{
public:
XmlFileGenerateTimer(sig_log& lg);
~XmlFileGenerateTimer();
public:
void start();
void stop();
// 啟動xml資料生成定時器
void start_timer_xml();
// 停止xml資料生成定時器
void stop_timer_xml();
private:
// IO_CONTEXT
boost::asio::io_context m_io_context;
// xml資料定時生成的定時器
// 湖北在每月3日、13日、23日8時推送資料,湖南在10時推送資料
boost::asio::deadline_timer m_timer_xml;
boost::thread m_thread;
// 第一次運行時
bool m_is_first_generate = true;
// 定時上傳的時間(默認為1分鐘)
int m_xmlRate = 1;
volatile bool m_bRun = false;
};
// 源檔案
#include "XmlFileGenerateTimer.h"
#include "DateFormat.h"
#include "SetUpConf.h"
#include "MSSQLProc.h"
#include "xmlDataConf.h"
#include <iostream>
#include <Windows.h>
XmlFileGenerateTimer::XmlFileGenerateTimer(sig_log& lg)
: my_log(lg)
, m_io_context()
, m_timer_xml(m_io_context)
{
}
XmlFileGenerateTimer::~XmlFileGenerateTimer()
{
stop();
}
void XmlFileGenerateTimer::start()
{
m_bRun = true;
start_timer_xml();
// 創建xml檔案生成執行緒
m_thread = boost::thread(boost::bind(&boost::asio::io_context::run, &m_io_context));
while (m_bRun)
{
msleep(1000); // 休眠1秒
}
}
void XmlFileGenerateTimer::stop()
{
m_bRun = false;
m_io_context.stop();
m_io_context.reset();
stop_timer_xml();
if (m_thread.joinable())
{
m_thread.join();
}
}
// 啟動xml資料生成定時器
void XmlFileGenerateTimer::start_timer_xml()
{
time_t next_point = DateFormat::now_s();
if (m_is_first_generate) // 如果是第一次生成xml檔案,則延時5s
{
m_is_first_generate = false;
next_point += 5; // 延遲5s上傳
}
else
{
// 每隔45秒定時檢測一次時間,判斷當前時間是否是當前月的3號、13號、23號的8點
next_point = (next_point / 45 + 1) * 45 + 2;
}
m_timer_xml.expires_at(boost::posix_time::from_time_t(next_point));
m_timer_xml.async_wait([this, next_point](boost::system::error_code ec) {
if (!ec)
{
// 獲取下劃線的年月日時間字串 yyyy_MM_dd
tm* t = std::localtime(&next_point);
int year = t->tm_year + 1900;
int month = t->tm_mon + 1;
int day = t->tm_mday;
int hour = t->tm_hour;
int minute = t->tm_min;
int second = t->tm_sec;
char strBeginTime[40] = { 0 };
char strEndTime[40] = { 0 };
if ((day == 3 || day == 13 || day == 23)
&& hour == 8 && minute == 0 )
{
if (day == 3) // 3號 生成上月下旬的資料
{
if (month == 1)
{
// 若是新年的開始1月份,則起始時間需要特殊處理
// (2020-01-03 08:00 例如 2019-12-21 01:00:00 ~ 2020-01-01 00:00:00)
sprintf(strBeginTime, "%04d-12-21 01:00:00", year - 1);
sprintf(strEndTime, "%04d-%02d-01 00:00:00", year, month);
}
else
{
// 2019-11-03 08:00
// 2019-10-21 01:00:00 ~ 2019-11-01 00:00:00
sprintf(strBeginTime, "%04d-%02d-21 01:00:00", year, month - 1);
sprintf(strEndTime, "%04d-%02d-01 00:00:00", year, month);
}
}
else if (day == 13) // 13號 生成本月上旬的資料
{
sprintf(strBeginTime, "%04d-%02d-01 01:00:00", year, month);
sprintf(strEndTime, "%04d-%02d-11 00:00:00", year, month);
}
else // 23號 本月中旬
{
sprintf(strBeginTime, "%04d-%02d-11 01:00:00", year, month);
sprintf(strEndTime, "%04d-%02d-21 00:00:00", year, month);
}
String currentTime = DateFormat::to_std_string();
std::cout << "[" << currentTime << "]" << " 開始xml定時生成任務" << std::endl;
unsigned long tStart = GetTickCount();
xmlDataConf xmlConf(signal_log_);
//xmlConf.generate_xmlFile(strBeginTime, strEndTime); // 每個點位站點一個xml檔案,10天左右109個站點也就是109個
xmlConf.generate_oneXmlFile(strBeginTime, strEndTime); // 109個站點采用同一個檔案,10天1個檔案,1個月也就是3個xml檔案
unsigned long tEnd = GetTickCount();
currentTime = DateFormat::to_std_string();
std::cout << "[" << currentTime << "]" << "xml定時生成任務完成,"
<< "耗時:" << (tEnd - tStart) << "毫秒" << std::endl;
}
// 再次啟動定時器
start_timer_xml();
}
});
}
// 停止xml資料生成定時器
void XmlFileGenerateTimer::stop_timer_xml()
{
m_timer_xml.cancel();
}
我的代碼的邏輯是,每隔45秒定時檢測一次時間,判斷當前時間是否是當前月的3號、13號、23號的8點0分,但是這樣會帶來一個問題,會重復生成多個XML檔案。
我知道了Linux下有crontab可以開啟定時任務,讓某個腳本在每個月的3號、13號、23號的8點定時執行;Java中有Quartz可以實作此功能,但是我不知道Boost的異步定時器如何實作這一點?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/69215.html
標籤:工具平臺和程序庫
下一篇:c++
