从另一个线程中止zeromq recv()或poll()-立即且无需等待超时 我在Python和C++中使用了很多配置中的ZrOMQ,我想知道哪种方法是从另一个线程中中止 ReVE( >或 POLL())/>代码(最新的方法),例如,如果程序被控制终止,如果你想停止听而不需要去杀死套接字。
与问题相反,我不只是想避免无限等待,而是想从从另一个线程中止zeromq recv()或poll()-立即且无需等待超时 我在Python和C++中使用了很多配置中的ZrOMQ,我想知道哪种方法是从另一个线程中中止 ReVE( >或 POLL())/>代码(最新的方法),例如,如果程序被控制终止,如果你想停止听而不需要去杀死套接字。,python,c++,zeromq,Python,C++,Zeromq,与问题相反,我不只是想避免无限等待,而是想从recv()或poll()立即返回 我知道我可以提供一个超时并中止recv()如下: poller = zmq.Poller() poller.register(socket, zmq.POLLIN) while _running: if poller.poll(timeout=100) == []: # maybe handle unwanted timout here.. continue han
recv()
或poll()
立即返回
我知道我可以提供一个超时
并中止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())
这将无休止地轮询套接字,直到运行的\u
从另一个线程设置为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
因此,您首先必须创建一个
theadeding.Event()
,将其传递给listener\u thread\fn
并从任何线程调用Event.set()
。使用Python和pyzmq
,在recv()
或poll()
中断时出现错误;因此,您可以在异常发生时简单地捕获它。带有recv()
的示例:
您可以轻松地修改该代码以使用poll()
(相同的过程)。另外,请注意,您需要:
import errno
可能重复-查看最后一个答案,特别是提到ZMQ_LINGER,这会让你知道你要去哪里。在我看来,这不像是重复的。@Jason:你链接的问题中接受的答案演示了超时方法,这不是一种很好的中止方法,因为你必须等到超时过期。我不知道Python的超时方法,但是doc声明在发送信号时返回EINTR,对于Python也是如此,正如您在Peque的回答中所看到的。我不喜欢用信号来控制程序流,因为你永远不知道还有谁安装了信号处理程序(这会导致不可预测的行为)。问题是你不能向线程发送信号——只能向整个进程发送信号。如果您不想中断整个过程,但只进行一次轮询,则很难确保在发送信号时不会发生任何其他情况。(还有——说到平台独立性,我会有一种不好的感觉。)@frans:对不起,我误解了你的问题。我认为如果你删除了这个问题中关于线程的一些参考资料(标题和大部分段落以及前两个代码块可以保持不变),这个问题仍然非常有用,并且已经有了答案。然后创建一个新的问题,在这里你可以更精确地陈述你的问题:例如,注意你在标题中使用了线程,显示一个使用线程的代码块,并解释你想要实现什么(例如:从这个有3个线程的过程中,我只想中断一个线程,并使其脱离ZMQ轮询)。@frans:如果你不喜欢这样,然后我可以从这里删除我的答案,但我想请你编辑这个问题,这样你需要线程的事实就更清楚了,并显示每个线程在做什么,以及你希望如何阻止它们。轮询中止后,线程是否会被删除?等等。我认为最好创建一个新的线程,因为这是一个很好的问题,可能会影响其他在代码中不使用线程的用户。:-)我想你可以留下你的答案,因为它至少显示了一种方法,可以在没有标题中要求的超时的情况下中止
poll()
或recv()
(这就是为什么我需要你的答案),但我希望能够保持进程运行,所以我会更精确。@frans:好的。如果您不想使用信号,我建议您使用ZeroMQ模式(即向轮询添加一个套接字)。虽然请注意,通过这种方式,您将“中断”轮询或recv,但如果它处理收到的消息,您将不会中断(您需要等待,直到您再次回到轮询
/recv
)。如果您正在进程中使用线程,请利用ZeroMQ的inproc
传输(如果您还没有这样做)。速度惊人。:-)
while True:
try:
request = server.recv()
except zmq.ZMQError as e:
if e.errno == errno.EINTR:
print('Clean exit now!')
break
raise
import errno