我在docker容器中运行了一个python“Device”。它连接到Crossbar路由器,在订阅频道上接收高速公路/ WAMP事件消息。
当某个事件发布时,我的设备正在调用一个在几秒钟内完成的方法。 现在,我希望它跳过或处理接收到的同一事件的任何消息,而该方法仍在运行。我试图通过使用Twisted的@inlinecallback装饰器并在设备上设置“self.busy”-flag来实现这一点。
但是它不会立即以延迟方式返回,而是表现得像普通的阻塞方法,因此传入的消息会被一个接一个地处理。
这是我的代码:
from autobahn.twisted.wamp import ApplicationSession
from twisted.internet.defer import inlineCallbacks
class Pixel(ApplicationSession):
@inlineCallbacks
def onJoin(self, details):
yield self.subscribe(self.handler_no_access, 'com.event.no_access')
@inlineCallbacks
def handler_no_access(self, direction):
entries = len(self.handlers['no_access'][direction])
if entries == 0:
self.handlers['no_access'][direction].append(direction)
result = yield self._handler_no_access()
return result
else:
yield print('handler_no_access: entries not 0: ', self.handlers['no_access'])
@inlineCallbacks
def _handler_no_access(self):
for direction in self.handlers['no_access']:
for message in self.handlers['no_access'][direction]:
yield self._timed_switch(self.direction_leds[direction], 'red', 0.2, 5)
self.handlers['no_access'][direction] = []
顺便说一句,我已经使用self.handler字典采用了hacky路径。
修改
阻止方法是:
yield self._timed_switch(self.direction_leds[direction], 'red', 0.2, 5)
它控制RaspberryPi的GPIO上的Neopixel,让它闪烁1秒。进一步调用方法
def handler_no_access(self, direction)
虽然_timed_switch尚未完成,但应跳过,因此它们不会叠加。
解
@inlineCallbacks
def handler_no_access(self, direction):
direction = str(direction)
if self.busy[direction] is False:
self.busy[direction] = True
# non-blocking now
yield deferToThread(self._handler_no_access, direction)
else:
yield print('handler_no_access: direction {} busy '.format(direction))
def _handler_no_access(self, direction):
# this takes 1s to execute
self._timed_switch(self.direction_leds[direction], 'red', 0.2, 5)
self.busy[direction] = False
答案 0 :(得分:0)
inlineCallbacks
不会将阻止代码转换为非阻塞代码。它只是使用Deferreds的替代API。延迟只是管理回调的一种方式。
您需要以其他方式将阻止代码重写为非阻塞。您实际上没有说过代码的哪一部分是阻塞的,也没有说它阻塞了什么,所以很难建议你如何做到这一点。将阻塞代码转换为非阻塞的唯一两个通用工具是线程和进程。因此,您可以在单独的线程或进程中运行该函数。该函数可能会或可能不会在这样的执行上下文中工作(再次,如果不知道它究竟是什么,就无法知道)。