我的应用程序的一部分由一个主线程和几个工作线程组成,这些工作线程使用pyzmq
套接字将其结果发送到主线程。主线程正在运行tornado IOloop
,并使用async
函数来读取使用future.context
创建的各种套接字类型上的传入数据。
出于性能原因,我想使用inproc
协议。但是inproc
仅在主线程和工作线程共享相同的上下文时才有效。另一方面,这将要求每个工作线程都需要运行tornado IOloop
,我认为这对于简单的工作人员来说有点过头了。
说明问题的最小示例:
import time
from threading import Thread
import zmq
from zmq.eventloop.future import Context as FutureContext
import tornado.ioloop
def worker(ctx):
socket = ctx.socket(zmq.PUSH)
socket.bind('inproc://worker')
while True:
# Do some work
time.sleep(2)
socket.send_pyobj("Work done")
async def mainLoop(ctx):
socket = ctx.socket(zmq.PULL)
socket.connect('inproc://worker')
while True:
#print(socket.recv_pyobj())
print(await socket.recv_pyobj())
normalCtx = zmq.Context()
futureCtx = FutureContext()
t = Thread(target=worker, kwargs=dict(ctx=normalCtx))
t.start()
# wait for bind to be effective
time.sleep(4)
io_loop = tornado.ioloop.IOLoop.current()
io_loop.spawn_callback(mainLoop, ctx=futureCtx)
io_loop.start()
在该示例中,PULL
套接字不会接收消息,因为它是在与工作程序套接字不同的上下文中发出的。如果我在两个线程中都使用normalCtx
(除去await
),则该示例运行良好。使用TCP作为传输协议时,它也可以正常工作。
我发现要使其正常运行的解决方案是:
normal
上下文并放弃async/await
。future
上下文并在每个worker中运行一个ioloop
。我的问题是,是否有一个魔术技巧可以使它与async/await
,inproc
一起工作,而不必在工人中运行ioloops
,例如通过以future
的方式访问non-future
上下文?