在扭曲中使用我自己的主循环
我有一个现有的程序,该程序有其自己的主循环,并且会根据接收到的输入进行计算-
假设是从用户那里简化的。我现在想在远程而不是本地进行计算,因此我决定在Twisted中实现RPC。
理想情况下,我只想更改我的一个功能,例如doComputation()
,以调用twist来执行RPC,获取结果并返回。该程序的其余部分应保持不变。但是,我该怎么做呢?我打电话时,Twisted劫持了主循环reactor.run()
。我还读到您实际上并没有扭曲线程,所有任务都按顺序运行,所以看来我不能只创建LoopingCall并以这种方式运行我的主循环。
-
根据现有程序的主循环类型,您可以有几种不同的选择。
如果它是GUI库中的mainloop,则Twisted可能已经支持它。在这种情况下,您可以继续使用它。
您也可以编写自己的反应堆。没有很多好的文档,但是您可以看看qtreactor在Twisted外部实现Reactor插件的方式。
您还可以使用编写最小反应器
threadedselectreactor
。有关此文档的文档也很少,但是使用它实现了wxpython反应器。我个人不建议使用这种方法,因为它很难测试,并且可能导致混乱的竞争状况,但是它的优点是可以让您利用Twisted的
几乎 所有默认网络代码进行 几乎 所有的包装。如果您确实确定不希望
doComputation
异步,并且希望在等待Twisted回答时阻止程序,请执行以下操作:- 在主循环启动之前,在另一个线程中启动Twisted
twistedThread = Thread(target=reactor.run); twistedThread.start()
- 实例化一个对象以
RPCDoer
在您自己的主循环线程中进行RPC通信(例如),以便您可以对其进行引用。确保真正开始使用Twisted逻辑,reactor.callFromThread
因此您不需要包装所有Twisted API调用。 - 仅使用Twisted API调用即可实现实现Deferred的
RPCDoer.doRPC
返回(即,无需调用现有的应用程序代码,因此您不必担心应用程序对象的线程安全;将所需的所有信息作为参数传递)。doRPC
-
您现在可以
doComputation
像这样实现:def doComputation(self): rpcResult = blockingCallFromThread(reactor, self.myRPCDoer.doRPC) return self.computeSomethingFrom(rpcResult)
-
切记
reactor.callFromThread(reactor.stop); twistedThread.join()
从主循环的关闭过程中调用,否则可能会在退出时看到一些令人困惑的回溯或日志消息。
最后,您应该真正考虑的一个选项,尤其是从长远来看:转储现有的主循环,并找出一种仅使用Twisted的方法。以我的经验,这是在这样的问题中,十分之九的答案。我并不是说这
总是 要走的路-
在很多情况下,您确实需要保持自己的主循环,或者花太多精力摆脱现有循环。但是,维护自己的循环也是可行的。请记住,Twisted回路已经过数百万用户的广泛测试,并已在多种环境中使用。如果您的循环也非常成熟,那可能没什么大不了的,但是如果您正在编写一个小的新程序,那么可靠性上的差异可能会很大。 - 在主循环启动之前,在另一个线程中启动Twisted