繁体   English   中英

C ++`Timer`类实现

C++ `Timer` class implementation

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我设计了一个Timer类,它每n n秒调度一次事件(使用Observer模式)。 当然它会创建一个新线程,以便不阻止调用它的线程。

然后我想 - 嗯......让我们说100个客户端连接到我的服务器程序,我为每个客户端创建了3个计时器,所以我运行了300个线程。 不是很多吗? 它是ok ,我运行300个线程?

然后我被告知 AS3 Timer在主线程中运行。 我想知道:怎么样? 如何实现在主线程中运行的计时器而不是阻塞它? 在C ++中有可能吗?

7 个回复

一种可能的解决方案是只为所有计时器使用一个线程,并按超时排序队列。 这个问题是当一个计时器到期并且你调用回调函数时,它将在全局计时器线程的上下文中运行而不是单独运行。这当然可以通过为事件生成一个新线程来解决,这是然后直接加入,或者通过一个线程池来处理事件,因此主计时器线程不会“堵塞”。

您可以创建一个单一的计时器线程,并为每个“注册”的客户端创建一个树中的条目。 密钥是客户端超时,值将是对客户端的引用。 这将通过超时对客户进行排序。

然后对于计时器,设置循环计时器,比如说每100毫秒(相应地调整)。 当计时器到期时,迭代树删除并调度已超时的每个客户端。 当您达到尚未超时的客户端超时时,迭代应该停止。

这种方法的更准确的改进是当计时器到期,并且调度客户端,计算下一个客户端的超时并相应地设置计时器。 这取决于解决方案需要的准确程度。

现在这是一个设计问题,所以每个人都有不同的意见,这也取决于你的要求,但IMO,计时器不应该决定线程策略本身 - 客户端应该这样做。

我不确定您期望的行为,但如果您在同一个线程上的计时器上运行300个事件,并且由于某种原因在一个事件处理程序块上运行,则永远不会触发其他事件处理程序。

一种可能性是在线程上创建一个计时器,但是以一种通过线程池在其他线程上执行事件处理程序的方式实现它。 当然,仍有可能破坏事物,因为如果你有许多长时间运行的处理程序,线程池可能会耗尽。

我强烈建议不要为每个处理程序使用显式的新线程,因为上下文切换可能会破坏性能。 线程池在平衡这个方面要好得多。

就在主线程中实现定时器而言,必须存在一些定期从用户代码调用的机制(例如,在事件轮询期间),该机制也处理定时器。 当然,这种方法很可能是不准确的,因为它只能在主线程中的用户代码允许时才执行定时器。

当然,它也会在执行回调代码时阻塞主线程。

你的第一个问题已经有了足够的答案:一个处理计时器事件的线程池(一组5或10个线程)通常是这样做的,并且每个事件的一个线程和所有事件的一个线程之间有一个很好的折衷方案。 。

关于第二个问题:使用常规编程意味着您无法在主线程中执行计时器事件处理程序。 如果可以,它会“阻塞”主线程,但如果没有得到主线程中执行的代码的同意和支持,这是不可能的。

主线程必须不时停止并检查定时器是否有事件,以对象的形式从定时器中获取参数,然后处理事件。 有很多方法可以设计这个原理,但这是你如何做到这一点的一般方法。

在Unix系统上你也可能会想到使用信号,但我认为这不是一个好主意。

您的服务器可以为所有计时器运行一个计时器线程。 当客户机计时器注册到服务器计时器轮时,此timer wheel会创建事件。 当注册的计时器超时时,事件由计时器轮设置。 客户端获取定时器注册时创建的事件的句柄。 客户端可以等待发出注册的定时器超时的事件。 这样,线程创建取决于客户端。

由于您使用C ++进行设计,因此可以使用Boost ASIO定时器。 我还设计了一个基于它们的Timer类,它运行良好,没有任何线程 - 它使用异步调用操作系统,所以基本上你只需要定义一个回调,当定时器到期时调用它,然后调用定时器的async_wait功能,非阻塞。 当你声明你的计时器对象时,你只需要传递一个io_service对象,它是OS的ASIO接口。这个对象负责处理异步请求和回调,所以你可以调用它的阻塞方法运行 在我的情况下,我不能让主线程阻塞,所以我只有一个线程,其中这个唯一的调用阻止。

在这里,您可以找到有关如何使用Boost ASIO异步计时器的示例:

http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/tutorial/tuttimer2.html

我的AbstractAsioTimer类被设计为子类,因此onTimerTick方法将特定于派生类的末尾。 虽然您的需求可能会略有不同,但它可能是一个很好的起点:

abstractasiotimer.hpp:

#ifndef _ABSTRACTASIOTIMER_HPP_
#define _ABSTRACTASIOTIMER_HPP_

#include <boost/asio.hpp>

/**
 * Encapsulates a POSIX timer with microsecond resolution
 */
class AbstractAsioTimer
{
  public:
    /**
     * Instantiates timer with the desired period
     * @param io ASIO interface object to the SO
     * @param timeout time in microseconds for the timer handler to be executed
     */
    AbstractAsioTimer(boost::asio::io_service& io, unsigned int timeout);

    /**
     * Destructor
     */
    virtual ~AbstractAsioTimer();

    /**
     * Starts timer operation
     */
    void timerStart();

    /**
     * Stops timer operation
     */
    void timerStop();

    /**
     * Returns timer operation state
     */
    bool isRunning() const;

    /**
     * Returns a reference to the underlying io_service
     */
    boost::asio::io_service& get_io_service();

  protected:
    /**
     * Timer handler to execute user specific code
     * @note must be reimplemented in derived classes
     */
    virtual void onTimerTick() = 0;

  private:
    /**
     * Callback to be executed on timer expiration. It is responsible
     * for calling the 'onTimerTick' method and restart the timer if 
     * it remains active
     */
    void timerExpired(const boost::system::error_code& error);

    boost::asio::deadline_timer timer; /**< ASIO timer object */
    unsigned int timeout; /**< Timer period in microseconds */
    bool running; /**< Flag to indicate whether the timer is active */
};
#endif

abstractasiotimer.cpp:

#include <iostream>
#include <boost/bind.hpp>
#include <boost/concept_check.hpp>
#include "abstractasiotimer.hpp"

using namespace boost::asio;

AbstractAsioTimer::AbstractAsioTimer(boost::asio::io_service& io, 
                                     unsigned int timeout):
                                     timer(io), timeout(timeout),
                                     running(false)
{

}

AbstractAsioTimer::~AbstractAsioTimer()
{
  running = false;
  timer.cancel();
}

void AbstractAsioTimer::timerExpired(const boost::system::error_code& error) {

  if (!error) {
    onTimerTick();
    //Restart timer
    timerStart();
  }
  else {
    running = false;
    std::cerr << "Timer stopped: " << error.message() << std::endl;
  }
}

void AbstractAsioTimer::timerStart()
{
  timer.expires_from_now(boost::posix_time::microseconds(timeout));
  timer.async_wait(boost::bind(&AbstractAsioTimer::timerExpired,
                   this, placeholders::error));
  running = true;
}

void AbstractAsioTimer::timerStop() {
  running = false;
  timer.cancel();
}

bool AbstractAsioTimer::isRunning() const {
  return running;
}

io_service& AbstractAsioTimer::get_io_service()
{
  return timer.get_io_service();
}
1 如何在Java中实现Timer类?

最近,我一直在开发一些android应用程序,发现android.os.Handler类非常适合实现.NET Timer(我的意思是System.Windows.Forms.Timer和System.Timers.Timer )。 如果您不知道什么是.NET计时器,则该计时器可以停止,可以 ...

2 改进C ++中的timer(timeout event)的实现

我的情况是这样的:该程序使用两个线程,我们将它们称为“发件人”和“收件人”,因为它是进程间通信的一种机制。 发送消息后,“发件人”线程停止在std::condition_variable和.wait (Lock)功能提供的std::condition_variable 。 “收件人”线程 ...

3 Arduino:在C ++类中使用Timer

我正在尝试使用计时器随着时间的推移反复更改PWM输出,以在亮度变化时进行平滑过渡。 尝试编译代码时,我不断收到此错误: /Users/jt/Documents/Arduino/libraries/SingleColorLight/SingleColorLight.cpp:在构造函数' ...

4 在Selenium和C#中使用Timer类

我正在使用Selenium登录到网页,然后转到该网站的“主页”。 在大多数情况下,我会打电话给: 该驱动程序的声明要早得多,但我在这里供参考。 通常,这就是我所需要的,然后代码将执行我想要的工作。 但是,在这种情况下,登录页面会通过几个不同的“ http:// ...” ...

5 c#Timer类更改(dueDate,periord)

我已经通过msdn库了解这个计时器类更改函数, http://msdn.microsoft.com/en-us/library/yz1c7148.aspx public bool Change(int dueTime,int period) 但我不明白什么是期间参数。 我 ...

2012-05-07 11:35:17 2 1983   c#
6 Thread.Sleep是在C#中实现我自己的Timer的正确方法吗?

我知道System.Threading.Timer存在,但是我已经有一个线程。 该线程应该一直保持活动状态,但仅每X秒执行一次。 测试实现如下所示: Run方法将执行,然后睡眠5分钟,然后再次执行。 因此,基本上,这是一个计时器,每5分钟触发一次+执行该操作所需的时间。 (是的, ...

7 如何在Linux下用C实现timer的回调函数

我已经在很多论坛上搜索了可能的解决方案好几天但没有运气; (我在这里发布我的问题,非常感谢你的回复。 IDEA:使用脚本来控制灯光(在Linux下的C语言中) 应用场景我有三个灯:红色,蓝色和绿色。 该脚本具有控制它们的计划。 例如,从现在起10秒钟,打开红灯2秒钟; 从现在 ...

8 C#-Xamarin表单无法与Timer类一起使用

我正在用Xamarin Forms开发一个应用程序,并希望用户按下一个使数字弹出的按钮,顺序是3-2-1,然后切换到其他表单。 这是我所拥有的 其中OneImage,TwoImage和ThreeImage是我的MainPage.xaml中的Image对象,它们的名称适当且“ IsV ...

9 正确使用Timer类

我想知道我写的代码是否是一个正确编写的代码,它确实起作用,但我之前做过不好的设计,所以我需要知道我是否以正确的方式思考这个问题。 代码是关于使用System.Timers.Timer每X小时执行一次重复操作。 我在stackoverflow上读了一些关于这个主题的线程,然后我尝试编写自己 ...

10 用Timer类编写Parceable

我是Android应用程序的新手,我将与Parceable合作,通过Intent发送课程。 我编写了一个Class,它具有一些属性,在其他属性(例如id,description)中,我有一个Timer 。 MyClass类似于: 那么,如何在课堂上将Timer与parceab ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2021 STACKOOM.COM