以轮询的间隔执行代码

Posted

技术标签:

【中文标题】以轮询的间隔执行代码【英文标题】:Executing code at an interval, with polling 【发布时间】:2016-08-24 22:38:10 【问题描述】:

我尝试在具有有限库函数的嵌入式设备上用 C++ 实现周期性事件。我不能使用睡眠或其他延迟,因为它会停止当前的执行。

例如。

do

    if(something)
    
       //Do something
    

    if(something)
    
       //Do something
    

    if(every 5 minutes)
    
       //Do something only once after 5 minutes
    

while(true)

我不知道该怎么做。你能帮我解决这个问题,因为我需要在这个 do while 循环中实现它吗?我会使用线程,但在这个设备上这实际上是不可能的,所以我正在寻找另一种方法。

【问题讨论】:

如果只有一种方法可以在循环中获取当前时间... 您是在 POSIX 系统上运行它吗?您可以在 5 分钟后使用alarm() 发送信号,信号处理程序将执行您想要的操作。 或者,在一个推动下,孵化一个std::threadsleep。但只有在绝望的情况下——线程不是空闲的。 你可能想在这里设置一个事件循环,或者使用像libuv这样的现成的,它为你提供了很多计时器功能。 @RadLexus,我很高兴你喜欢我的幽默 :-) 【参考方案1】:

当然,生成单独线程(我会这样做)或使用 cmets 中给出的alarm() 的建议是很好的建议,但在您的设备上可能无法实现。但是,专注于您当前的方法,通常的想法是伪代码:

last action time = current time

while (true) 
   do things.
   if current time - last action time >= 5 minutes then
       perform action
       last action time = current time
       // or last action time += 5 minutes if you want to mitigate drift
   end

所以现在你只需要选择你最喜欢的方式来获取当前时间。在桌面平台上,您可以使用例如Windows 上的time()gettimeofday()GetTickCount() 等。一些嵌入式平台也可能提供这些。但是,这可能会有问题:

由于您在评论中提到您正在使用嵌入式设备,“您最喜欢的获取当前时间的方式”会因平台而异,您只需查看设备文档即可。如果幸运的话,您的 MCU 可能会提供一种查询 CPU 计数器的方法,以及您通常已经从设置中知道的频率。但它可能不会。

如果没有,另一种选择是您的设备是否提供板载计时器。在这种情况下,您可以对其进行配置并响应周期性中断,在这种情况下,您的两个选项通常是:

    在定时器中断处理程序中执行该操作 - 但仅当它很短时才执行此操作,并且为中断安全采取适当的预防措施。 在定时器中断处理程序中设置volatile 标志,在主循环中检查该标志并执行操作 + 如果已设置则在此处重置标志。这通常是一种更简单的方法。

这样做在架构上类似于使用alarm()。但是,当然也有实现time() 和/或gettimeofday() 的嵌入式平台。但这些都是你的选择。

【讨论】:

@Myst 我总是认为有些人不喜欢我的头像错误地将长颈鹿描绘成脖子短的事实。 不是我的 DV,但我认为这不是一个好的答案。其实这个问题不好,也太宽泛了。 “大多数 MCU 提供了一种查询 CPU 计数器和频率的方法。” - 完全错误。几乎没有任何小于 32 位的 MCU 甚至有 CPU 计数器(可能是 -1 CPU,2 CPU?),而且几乎没有一个方法可以查询频率 - 如果没有定义的第二个参考时钟,它会如何?跨度> @Olaf 是的,这个问题很可疑。我试过了,但你知道他们说什么,不能擦亮粪便。至于答案,我将把“大多数”改为“一些……可能”,希望这能让你的灵魂平静下来,让我们度过这场巨大的悲剧。希望除了那个单一的定性词之外,我的回答的 rest 中至少有一些可取之处,但我完全理解这可能使整个事情无效。 (有趣的是,当我一开始写“大多数”时,我想,“也许我应该改变它……不,任何有头脑的读者肯定都能在这里明白这一点”)。【参考方案2】:

这听起来像是您在寻找两种不同的功能;一,在不中断执行的情况下发送命令;二、等待一定的时间。首先,您正在寻找异步编程。第二个,我推荐Boost::deadline_timer。要将两者结合起来,请查看 Boost::io_service,它允许您注册异步回调,无论是否使用计时器。

【讨论】:

我不能使用 boost,因为它非常大并且占用大量空间。我正在使用有存储限制的嵌入式设备 @RDoonds 您不觉得在您的问题中提及这些信息会很有用吗? o.O 据我所知,Boost 可以很好地嵌入。 ***.com/questions/166542/… 无论如何,io_service 和deadline_timer 只是建议。具有可变延迟的异步调度是您最好的选择。你用什么做线程?如果有的话,您的其他限制是什么?也许我还能帮忙。 等等,你没有使用线程但你不想停止执行?只需计算经过的时间并在达到阈值时执行。如果任何电话花费的时间过长或未能返回,那么您就不走运了;如果可能,使用某种形式的协程、部分结果或超时来降低这种风险。

以上是关于以轮询的间隔执行代码的主要内容,如果未能解决你的问题,请参考以下文章

vue分页列表轮询解决方案

服务器推Comet长轮询的方式与普通AJAX不断请求的方式的区别

设置元素等待

设置元素等待

如何在不轮询的情况下监视页面的更改?

Drone概念与答疑