我有一个小软件,我有一个单独的线程正在等待ZeroMQ消息。我正在使用ZeroMQ的PUB
/ SUB
通信协议。
目前我通过将变量“cont_loop
”设置为False
来中止该线程。
但是我发现,当没有消息到达ZeroMQ订阅者时,我无法退出该线程(不删除整个程序)。
def __init__(self):
Thread.__init__(self)
self.cont_loop = True
def abort(self):
self.continue_loop = False
def run(self):
zmq_context = zmq.Context()
zmq_socket = zmq_context.socket(zmq.SUB)
zmq_socket.bind("tcp://*:%s" % *(5556))
zmq_socket.setsockopt(zmq.SUBSCRIBE, "")
while self.cont_loop:
data = zmq_socket.recv()
print "Message: " + data
zmq_socket.close()
zmq_context.term()
print "exit"
我尝试将socket.close()
和context.term()
移至abort-method。因此,它关闭了订阅者,但这导致整个程序死亡。
关闭上述程序的正确方法是什么?
答案 0 :(得分:1)
答:有很多方法可以实现既定目标。让我选择一个,作为如何处理分布式进程到进程消息传递的模型示例。
首先。假设,典型的软件设计任务中有更多的优先级。一些更高,一些更低,一些甚至更低,可以推迟执行这些低优先级子任务,以便在调度程序中有更多时间执行那些无法处理等待的子任务。
这就是说,让我们查看您的代码。正在使用的 SUB
的.recv()
侧指令会导致两件事。一个可见 - 它在具有SUB
行为的ZeroMQ套接字上执行RECEIVE操作。第二个,较不明显的是,它仍然悬挂,直到它得到一些东西"兼容"当前状态为SUB
- 行为(稍后将详细说明)。
这意味着它也一直 BLOCKS ,因为这样的.recv()
方法调用 UNTIL 一些未知的,本地无法控制的状态/事件重合使其传递ZeroMQ消息,其内容与"兼容" 具有此(仍然阻塞)SUB
行为实例的本地预设状态。
这可能需要很长时间。
这正是为什么.recv()
在控制循环中被使用的原因,外部处理同时获得了机会&做你想做的事情的责任(包括与中止相关的操作以及在适当的资源和发布时公平/优雅的终止)。
接收流程变为 .recv( flags = zmq.NOBLOCK )
而非try: except:
集。这样一种方式,你的本地进程不会失去它对事件流的控制(包括NOP就是这样)。
花点时间阅读一本精彩的宝石书," Code Connected,第1卷",ZeroMQ的共同父亲Pieter HINTJENS已经发表(也作为PDF)。
他的许多想法和他与我们分享的错误确实值得你花时间。
享受ZeroMQ的力量。它非常强大而且功能强大。值得自上而下掌握。