在软件开发里,经常会遇到这样的情况,比如客户让我们开发的软件要求每隔半小时,就要备份一次数据,以便避免数据丢失。又比如在开发一个游戏网络服务器时,需要不断检查客户端连接上来的数据连接是否还有效,这时也需要使用一个任务来检查客户端的连接是否还有心跳包过来,如果没有心跳包,就可以把这个连接断开,释放相关的资源,避免服务器的资源永远占用,导致服务器运行时间长了就会死机。面对这些情况,在有界面的情况下,往往通过界面上的定时器来提供定时服务来解决这些问题。在没有界面的情况之下,往往使用一个线程来解决,虽然都可以解决,但相比boost库里的boost::asio::deadline_timer对象来解决,显示有点复杂,代码有点多,维护性也不好。下面就来看例子,怎么样简单优美地解决心跳包检查的问题:
// boost_017.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <iostream>
void TaskRun(int nVal)
{
//下面输出需要加锁,不能多个线程共享输出。
static boost::mutex mutexCout;
boost::lock_guard<boost::mutex> autoLock(mutexCout);
std::cout << "TaskRun: " << nVal << std::endl;
}
//封装线程组运行的类, 并且演示使用类成员函数作为线程组运行函数
class CThreadBase
{
public:
CThreadBase(void)
:m_Work(m_ioService),
m_HeartBeat(m_ioService)
{
}
void Start(int nMaxCount)
{
//循环地创建N个线程。
for (int i = 0; i < nMaxCount; ++i)
{
m_threadGroup.create_thread(boost::bind(&CThreadBase::Run, this, i));
}
}
void Stop(void)
{
//
m_ioService.stop();
//等所有线程退出。
m_threadGroup.join_all();
}
//测试任务队列
void TestTask(void)
{
//放入几个任务。
m_ioService.post(boost::bind(TaskRun, 1));
m_ioService.post(boost::bind(TaskRun, 2));
m_ioService.post(boost::bind(TaskRun, 3));
m_ioService.post(boost::bind(TaskRun, 4));
m_ioService.post(boost::bind(TaskRun, 5));
m_ioService.post(boost::bind(TaskRun, 6));
//第一次定时器启动。
m_HeartBeat.expires_from_now(boost::posix_time::milliseconds(5));
m_HeartBeat.async_wait(boost::bind(&CThreadBase::Wait, this, 5));
}
private:
virtual void Run(int nVal)
{
//运行队列里的任务。
boost::system::error_code errorCode;
m_ioService.run(errorCode);
}
//
void Wait(int nSeconds)
{
//下面输出需要加锁,不能多个线程共享输出。
static boost::mutex mutexCout;
boost::lock_guard<boost::mutex> autoLock(mutexCout);
std::cout << "Wait: " << nSeconds << std::endl;
//下一次定时器。
m_HeartBeat.expires_from_now(boost::posix_time::seconds(5));
m_HeartBeat.async_wait(boost::bind(&CThreadBase::Wait, this, 5));
}
private:
//定义一个任务队列。
boost::asio::io_service m_ioService;
boost::asio::io_service::work m_Work;
//定义一个线程组对象。
boost::thread_group m_threadGroup;
//创建定时器。
boost::asio::deadline_timer m_HeartBeat;
};
int _tmain(int argc, _TCHAR* argv[])
{
//
CThreadBase threadBase;
//设置最大的线程个数。
threadBase.Start(3);
threadBase.TestTask();
Sleep(20000);
threadBase.Stop();
system("pause");
return 0;
}
在这个例子里,定义了定时器boost::asio::deadline_timer对象HeartBeat,然后调用函数expires_from_now来设置定时的时间,最后调用函数async_wait异步调用函数Wait来执行。为了达到每间隔5秒调用一次,在函数Wait里递归地调用函数expires_from_now和函数async_wait。因此在这个例子里,函数Wait就是定时执行的函数,在这个函数添加代码,就可以实现定时地检查心跳包,定时备份的工作。这个例子输出的结果如下:
TaskRun: 1
TaskRun: 2
TaskRun: 3
TaskRun: 4
TaskRun: 5
Wait: 5
TaskRun: 6
Wait: 5
Wait: 5
Wait: 5
请按任意键继续. . .