Cla*_*diu 2 python multithreading shutdown twisted
我有一个客户端使用twisted连接到服务器.客户端有一个可能在后台执行操作的线程.当反应堆关闭时,我必须:
1) check if the thread is doing things
2) stop it if it is
Run Code Online (Sandbox Code Playgroud)
这是一种优雅的方式吗?我能做的最好的事情是:
def cleanup(self):
isWorkingDF = defer.Deferred()
doneDF = defer.Deferred()
def checkIsWorking():
res = self.stuff.isWorking() #blocking call
reactor.callFromThread(isWorkingDF.callback, res)
def shutdownOrNot(isWorking):
if isWorking:
#shutdown necessary, shutdown is also a blocking call
def shutdown():
self.stuff.shutdown()
reactor.callFromThread(doneDF, None)
reactor.callInThread(shutdown)
else:
doneDF.callback(None) #no shutdown needed
isWorkingDF.addCallback(shutdownOrNot)
reactor.callInThread(checkIsWorking)
return doneDF
Run Code Online (Sandbox Code Playgroud)
首先,我们检查它是否正常工作.该回调的结果rescallback是关闭或不关闭,然后触发doneDF,扭曲等待直到关闭.
相当混乱呃!有没有更好的办法?
也许一个相关的问题是,是否有更优雅的方式将回调链接到彼此?在完成后我可以看到自己需要做更多的清理代码,所以我必须做出一个不同的done延迟,并且当前doneDF激活一个回调,然后执行调用done延迟的调用.
啊,真正的答案是使用defer.inlineCallbacks装饰器.上面的代码现在变成:
@defer.inlineCallbacks
def procShutdownStuff(self):
isWorking = yield deferToThread(self.stuff.isWorking)
if isWorking:
yield deferToThread(self.stuff.shutdown)
def cleanup(self):
return self.procShutdownStuff()
Run Code Online (Sandbox Code Playgroud)
您可以通过使用deferToThread而不是callInThread/ callFromThreadpairs 来简化这一点:
from twisted.internet.threads import deferToThread
def cleanup(self):
isWorkingDF = deferToThread(self.stuff.isWorking)
def shutdownOrNot(isWorking):
if isWorking:
#shutdown necessary, shutdown is also a blocking call
return deferToThread(self.stuff.shutdown)
isWorkingDF.addCallback(shutdownOrNot)
return isWorkingDF
Run Code Online (Sandbox Code Playgroud)
deferToThread 基本上只是你在你的函数版本中实现两次的相同线程逻辑的一个很好的包装器.