从另一个线程中止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