我在许多配置中使用Python和C ++中的ZeroMQ,我想知道哪种方法是从另一个线程中止recv()
或poll()
的最优雅方式(例如,在受控程序的情况下)终止,但如果你想停止听,而不需要杀掉套接字)。
与this问题相反,我并不想避免不定期等待,但我想立即从recv()
或poll()
返回 。
我知道我可以像这样提供timeout
和中止recv()
:
poller = zmq.Poller()
poller.register(socket, zmq.POLLIN)
while _running:
if poller.poll(timeout=100) == []:
# maybe handle unwanted timout here..
continue
handle_message(socket.recv())
这将无休止地轮询插座,直到_running
从另一个线程设置为False
- 在完成最多100毫秒之后。
但这并不好 - 我有一个繁忙的循环,这样很难处理真正的超时,这可能是由于不需要的行为造成的。我也必须这样做 等待超时,这在大多数情况下并不重要,但是......你知道我的意思。
当然,我可以轮询一个额外的插座用于堕胎:
abort_socket = context.socket(zmq.SUB)
abort_socket.setsockopt(zmq.SUBSCRIBE, b"")
abort_socket.connect(<abort-publisher-endpoint>)
poller = zmq.Poller()
poller.register(socket, zmq.POLLIN)
poller.register(abort_socket, zmq.POLLIN)
while _running:
poll_result = poller.poll(timeout=1000)
if socket in poll_result:
handle_message(socket.recv())
elif abort_socket in poll_result:
break
else:
# handle real timeout here
pass
但这种方法也有缺点:
abort_socket
只能在一个帖子中使用,所以我必须确保所以我的问题是:这是怎么做到的好方法?
我能以某种方式使用像Python threading.Event
或s.th.这样的东西。类似于其他语言,而不是像这样传递给轮询器的abort-socket?:
def listener_thread_fn(event)
poller = zmq.Poller()
poller.register(socket, zmq.POLLIN)
poller.register(event, zmq.POLLIN)
while _running:
poll_result = poller.poll(timeout=1000)
if socket in poll_result:
handle_message(socket.recv())
elif event in poll_result:
break
else:
# handle real timeout here
pass
因此,您必须首先创建theading.Event()
,将其传递给listener_thread_fn
并从任何线程调用event.set()
以中止。
答案 0 :(得分:1)
使用Python和pyzmq
,在recv()
或poll()
中断时会出现错误;所以你可以在发生异常时捕获它。 recv()
的示例:
while True:
try:
request = server.recv()
except zmq.ZMQError as e:
if e.errno == errno.EINTR:
print('Clean exit now!')
break
raise
您可以轻松修改该代码以使用poll()
(其程序相同)。另请注意,您需要:
import errno