有无效率高的方法检测状态的变更

2016-08-18 19:50:20 +08:00
 SuperFashi

假如有一个参数,只能读取,检测这个参数变化的方法只有无限地获取参数数据并和上一次对比吗?

如果没有的话,假设这个参数就是一个按钮的状态, 0 或 1 的值。如果把两次检测的时间设的短的话,会很耗 CPU 资源;如果设的长的话有可能延迟明显,而且甚至有可能检测不到状态变更,有什么好的经验或者办法吗?

2065 次点击
所在节点    问与答
17 条回复
cxe2v
2016-08-18 20:01:51 +08:00
难道不可以在状态变更的时候通知一下观察者吗?
《观察者模式》?《订阅模式》
htfy96
2016-08-18 20:23:02 +08:00
给具体情景
SuperFashi
2016-08-18 21:08:50 +08:00
@cxe2v 无,一个参数,只能读取,其本身是无法进行任何行动的。

@htfy96 就比如有个按钮啊,但是这个按钮只能读取其状态,但其状态改变时无法通知回来。
cxe2v
2016-08-18 21:11:36 +08:00
@SuperFashi 参数你可以有访问器啊,类似 java 和 c#里都会有这个东西,访问器里就可以在属性变化的时候进行一些操作
oott123
2016-08-18 21:12:16 +08:00

基本没有

在某些场景下可以尝试慢慢增加读取间隔,一旦获取到变更之后又缩短。
lecher
2016-08-18 21:13:09 +08:00
换个思路,给这个参数的值变更加个方法, setValue 之类的,再写一个 bindEvent 专门用来传入需要绑定的事件,然后在 setValue 这个方法被调用的时候去调用 bindEvent 里面传入的事件,达到唤醒对应的绑定事件的目的。
这个方式是主动触发绑定事件的。效率和实时性都可以满足要求。
SuperFashi
2016-08-18 21:39:48 +08:00
@lecher @cxe2v 额,条件还要再苛刻点,假设那个值就是一个物理的值,比如一个物理按钮的开关的状态,获取时就是获取目前开关电势差,这样如何?
xmoiduts
2016-08-18 21:47:18 +08:00
@SuperFashi 我觉得这个例子不恰当,因为物理值可以配置中断,整个过程和 cpu 无关。
htfy96
2016-08-18 21:54:43 +08:00
@SuperFashi 一般硬件都有触发中断的机制。即使是按钮的话除了轮询之外一般都有办法让触发的时候调用某个方法如#6 。

很多时候并不是真的只能读取。页面上除非在做什么第三方插件之类的东西(即使是大多数情况下也可以强行绑定,只是手段比较黑而已),一般都可以的。

检测变化要么主动去读(轮询),要么被动等唤醒(中断),要么混合两者
SuperFashi
2016-08-18 22:27:31 +08:00
@xmoiduts @htfy96 那太底层了,目前还没有这个技术,有什么好的教程吗?
htfy96
2016-08-18 22:31:45 +08:00
@SuperFashi 给具体情景。如果是硬件给型号、接口;软件要有具体描述
SuperFashi
2016-08-18 22:35:50 +08:00
@htfy96 标准 GPIO 接口,再详细一点就是 RPi 上的
htfy96
2016-08-18 22:45:53 +08:00
@SuperFashi so 就有一贴 GPIO Events in Python ,可以事件驱动,注册一个回调函数的
htfy96
2016-08-18 22:51:10 +08:00
@SuperFashi 看了一下内部实现是另开了个线程 然后基于 epoll 实现的事件循环
SuperFashi
2016-08-18 23:05:12 +08:00
@htfy96 所以其实还是个循环吗,只不过是个系统级的?我也看了下实现,根本看不懂……
htfy96
2016-08-18 23:33:22 +08:00
@SuperFashi 首先注册 epoll 的时候,内部相当于告诉了系统,如果这个值发生了变化,就执行某个回调函数。
实现方式可能是:
系统设置 gpio 的中断使能寄存器。同时注册这个设备对应 irq 编号的处理函数。
当这根线变化的时候, gpio 对应的控制器上的硬件(因为中断使能寄存器打开)检测到(有可能是轮询; 也可能是硬件上做一个带延时的电路,如果与当前值异或所得结果为 1 ,说明发生了变化),向处理器的中断线发了信号。
处理器接到信号,根据来的线和种类,在内存中查找对应 irq 编号的处理函数,然后执行
billlee
2016-08-18 23:34:00 +08:00
@SuperFashi epoll 在没有事件发生的时候会阻塞,进程进入睡眠状态。硬件中断经过内核里的一系列 dispatch 后最后会把等待这个事件的进程唤醒。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/300261

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX