Asio是一个建立在Boost所提供的相关组件之上的异步的网络库,可以运行在Win/Linux/Unix等各种平台之上。

不过随着C++11的发布,其对Boost的依赖也越来越少,作者又做了一个不依赖于Boost的版本。

1.  同步Timer:  调用wait后立即阻塞

#include <iostream>
#include <boost/asio.hpp> int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer timer(io, boost::posix_time::seconds(5)); timer.wait(); std::cout << "Hello, world!" << std::endl; return 0;
}

实测效果,程序开始运行后3秒,打印了:Hello, world!

2.  异步Timer: wait后不立即阻塞,调用io的run方法时才会阻塞

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp> void print(const boost::system::error_code& err)
{
std::cout << "Hello, world! " << std::endl;
} int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer timer(io, boost::posix_time::seconds(5)); std::cout << "----gointo 0---- " << std::endl; timer.async_wait(&print);
//timer.cancel(); 取消定时器, 这样后续io.run方法将不会阻塞,但是定时器回调函数会立马被执行 std::cout << "----gointo 1---- " << std::endl; io.run();
std::cout << "----gointo 2-!--- " << std::endl; return 0;
}

运行:

2.1

如果让上图内的timer.cancel()这句代码工作,那么效果将是:

取消定时器后, 定时器回调函数会立马被执行,同时后续io.run方法将不会阻塞 

2.2

如果我们希望在开启定时器后,本线程内的代码流仍能继续向下走,

我们只有改一改代码了:将开启定时器的代码封装在一个新的线程内,这样阻塞的就不是本线程,而是新开的线程了。

如下面的例子3所示。

3  异步Timer:  将开启定时器的代码封装在一个新的线程内,这样阻塞的就不是本线程,而是新开的线程了。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp> void print(const boost::system::error_code& err)
{
std::cout << "Hello, world! " << std::endl;
} void func_timer_test()
{
boost::asio::io_service io;
boost::asio::deadline_timer timer(io, boost::posix_time::seconds(5)); std::cout << "----gointo 0---- " << std::endl;
timer.async_wait(&print);
std::cout << "----gointo 1---- " << std::endl; io.run();
std::cout << "----gointo 2---- " << std::endl;
} int main()
{
boost::thread thread_timer_test(func_timer_test);
thread_timer_test.detach(); while(1){
std::cout << "----main loop()--- " << std::endl;
boost::this_thread::sleep(boost::posix_time::seconds(1));
} return 0;
}

运行:

4  异步Timer:  取消定时器,因为取消定时器后,事先设置的定时器回调函数会被立马执行,所以必须在定时器回调函数内通过当前的错误码来进行判断。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/exception/all.hpp>
#include <boost/system/error_code.hpp>
#include <boost/asio.hpp>
#include <string> void print(const boost::system::error_code& err)
{
if(err){
std::cout << err.category().name() << std::endl;
std::cout << err.value() << std::endl;
} std::cout << "Hello, world! " << std::endl;
} int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer timer(io, boost::posix_time::seconds(5)); std::cout << "----gointo 0---- " << std::endl; timer.async_wait(&print);
timer.cancel(); std::cout << "----gointo 1-*--- " << std::endl; io.run(); std::cout << "----gointo 2-$--- " << std::endl; return 0;
}

4.1

如果屏蔽上图代码内的timer.cancel()这句,即不取消定时器时,

运行结果如下图:

存在5秒的定时。

4.2

取消定时器,即上图代码的运行结果:

代码立即执行完毕,且定时器回调内判断出,发生了异常。

那么,我们平常在使用boost库定时器的时候,如果我们希望真正取消一个事先已经设置好的定时器回调函数的执行,

我们可以换种思路:在定时器回调函数内做if-else判断,如果被取消了干啥(一般是空处理),定时结束正常进入时干啥,区分开处理就好了。

后记:

对于取消定时器任务,如果我在主线程内调用timer.cancel来取消定时器线程内的定时器任务,实测运行会段错误。

也即是说,本博客最终还是没能搞定单次定时器任务的取消。

百度了不少博客,都没能搞定定时器任务的取消。

需要重要说明的是:我所谓的取消定时器任务的严格定义是,我开了一个定时器任务,但是这个任务由于时间未到所以还没有被执行到,我中途希望取消该定时器任务。

https://blog.csdn.net/zhongjiezheng/article/details/44343959

这篇博客的访问量竟然还挺高的,但是他实现的是一个周期性定时器,他所谓的停止指的仅仅是取消这个定时器任务的周期性执行而已。和我所需要的取消定时器任务的需求完全是两码事。

我们来验证上面博客的代码是无法完成取消定时器任务的,复制其代码,简单修改了下,贴代码:

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <iostream> class MyTimer
{
public:
template<typename F>
MyTimer(boost::asio::io_service& ios, F func, int interval, bool start = true) :
m_func(func),
m_interval(interval),
m_timer(ios, boost::posix_time::millisec(interval)),
m_flag(start)
{
m_timer.async_wait(boost::bind(&MyTimer::call_func, this, boost::asio::placeholders::error));
}
void call_func(const boost::system::error_code&)
{
if (!m_flag)
{
std::cout << "cancel!" << std::endl;
return;
}
m_func();
//m_timer.expires_at(m_timer.expires_at() + boost::posix_time::millisec(m_interval));
//m_timer.async_wait(boost::bind(&MyTimer::call_func, this, boost::asio::placeholders::error));
}
void stop()
{
m_flag = false;
}
void start(int new_interval)
{
m_flag = true;
m_interval = new_interval;
m_timer.expires_from_now(boost::posix_time::millisec(m_interval));
m_timer.async_wait(boost::bind(&MyTimer::call_func, this, boost::asio::placeholders::error));
}
private:
boost::function<void()> m_func;
int m_interval;
boost::asio::deadline_timer m_timer;
bool m_flag;
}; void print1()
{
std::cout << "11111" << std::endl;
} void print2()
{
std::cout << "22222" << std::endl;
} boost::asio::io_service ios;
MyTimer at1(ios, print1, 15000); // 希望该定时器任务15秒后被执行,中途我们来取消之
//MyTimer at2(ios, print2, 8000); void threadfun()
{
boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
at1.stop(); //at2.start(1000); //at1.stop();
//at2.stop();
} int main()
{
// boost::this_thread::sleep(boost::posix_time::milliseconds(5000));
boost::thread_group thr_grp;
thr_grp.create_thread(boost::bind(threadfun));
ios.run();
getchar();
return 0;
} // 实验失败 定时器任务没有被取消。

运行:

实验失败 定时器任务没有被取消。

好吧,折腾得够久了,无比的烦躁。 我还是自己基于linux去封装一个CPP的定时器吧!

.

.

BOOST 定时器 stop探究的更多相关文章

  1. boost 定时器.

    #include <iostream> #include <boost/asio.hpp> int main() { boost::asio::io_service io; b ...

  2. 简单的几个Boost定时器

    boost的asio库里有几个定时的器,老的有 deadline_timer , 还有三个可配合 C++11 的 chrono 使用的 high_resolution_timer  . steady_ ...

  3. boost timer 定时器 Operation cancel !

    前面段时间处理一个定时器时,老是提示 操作取消. 硬是没搞明白为什么! 其实我遇到的这个情况很简单就是(boost::asio::deadline_timer timer)这个变量的生命同期结束了,对 ...

  4. 使用boost的deadline_timer实现一个异步定时器

    概述 最近在工作上需要用到定时器,然后看到boost里面的deadline_timer可以实现一个定时器,所以就直接将其封装成了ATimer类,方便使用,ATimer有以下优点: 可以支持纳秒.毫秒. ...

  5. boost库学习随记六:使用同步定时器、异步定时器、bind、成员函数回调处理、多线程的同步处理示例等

    一.使用同步定时器 这个示例程序通过展示如何在一个定时器执行一个阻塞等待. //makefile #-------------------------------------------------- ...

  6. [Boost基础]并发编程——asio网络库——定时器deadline_timer

    asio库基于操作系统提供的异步机制,采用前摄器设计模式(Proactor)实现了可移植的异步(或者同步)IO操作,而且并不要求使用多线程和锁定,有些的避免了多线程编程带来的诸多有害副作用(如条件竞争 ...

  7. boost asio 学习(六) 定时器

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=7 6 定时器 ...

  8. 使用boost线程定时器作为后台线程来切换主循环程序状态方法2

    上一篇的方法主要使用的是:通过线程延时实 现的定时,并且只能定时一次,如果需要对此定时处理,就需要使用下面的定时器: #include "stdafx.h" #include &l ...

  9. Tcp/ip实验准备:一个简单的定时器——boost实现

    tcp/ip实验须要在指定的时间查看结果,为了实验方便,做了一个定时器.用法是: 在命令行输入:timer 输入数字之后,计时对应秒数 输入m数字之后.计时对应分钟数(支持小数分钟数) 输入q退出. ...

  10. boost::asio学习(定时器)

    #include <boost/asio.hpp> #include <iostream> void handle1(const boost::system::error_co ...

随机推荐

  1. VScode配置PHP开发环境

    vscode配置php开发环境 使用vscode配置PHP开发环境,首先要下载vscode, vscode下载 下载完vscode之后,可以在扩展里面下载中文版本 将vscode下载完之后,需要下载x ...

  2. 【Spring-Security】Re07 持久化的记住我

    Security记住我功能底层实现依赖于SpringJDBC组件,如果有持久层框架的话,就由持久层框架实现 演示案例的选型,MysqlJdbc + MybatisStarter <depende ...

  3. Audio2Gesture:NVIDIA 黄仁勋的3D虚拟人技术 —— 元宇宙

    相关: https://www.nvidia.com/en-us/on-demand/session/omniverse2020-om1573/ https://www.nvidia.com/zh-t ...

  4. tf.metrics 使用过程中发现的一些问题

    起因是看到了这么一个帖子: http://www.cocoachina.com/cms/wap.php?action=article&id=86347 简短来说就是下面的代码   运行起来结果 ...

  5. 多网卡系统下如何使用tcp协议实现MPI的分布式多机运行(mpi的实现使用openmpi)

    如题: 最近在看MPI方面的东西,主要是Python下的MPI4PY,学校有超算机房可以使用MPI,但是需要申请什么的比较麻烦,目的也本就是为了学习一下,所以就想着在自己的电脑上先配置一下. 现有硬件 ...

  6. 纪念IE浏览器退役,哈哈哈!!!

    网址: https://haokan.baidu.com/v?pd=wisenatural&vid=16024148879625055169 ========================= ...

  7. FFmpeg开发笔记(四十六)利用SRT协议构建手机APP的直播Demo

    ​不管是传统互联网还是移动互联网,实时数据传输都是刚需,比如以QQ.微信为代表的即时通信工具,能够实时传输文本和图片.其中一对一的图文通信叫做私聊,多对多的图文通信叫做群聊. 除了常见的图文即时通信, ...

  8. SMU Spring 2023 Trial Contest Round 10

    A. Remove Duplicates 题意大概就是从左到右数字最先数完的最先输出 所以我们可以在输入每个数时记录每个数的出现次数,然后在循环一遍,每次该数字的次数减1,当数字的次数只剩1的时候就输 ...

  9. 我是如何使用 vue2+element-ui 处理负责表单,避免单文件过大的问题

    引言 在工作中我经常需要处理一些复杂.动态表单,但是随着需求不断迭代,我们也许会发现曾经两三百行的.vue文件现在不知不觉到了两千行,三千行,甚至更多... 这对于一个需要长期维护的项目,无疑是增加了 ...

  10. 组长:你熟悉过React,开发个Next项目模板吧,我:怎么扯上关系的?

    组长:你熟悉过React,开发个Next项目模板吧,我:怎么扯上关系的? 最近工作安排我开发一个Next.js项目模板,心里默笑,React用得少得都快忘光了,现在得搞Next?虽然我曾是React的 ...