2

我有一个客户端使用扭曲连接到服务器。客户端有一个线程,它可能在后台做事。当反应堆关闭时,我必须:

1) check if the thread is doing things
2) stop it if it is

什么是优雅的方式来做到这一点?我能做的最好的事情是一些令人困惑的事情,比如:

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

首先,我们检查它是否正常工作。该回调的结果进入rescallback关闭或不关闭,然后触发 doneDF,扭曲等待直到关闭。

好乱啊!有没有更好的办法?

也许一个相关的问题是,有没有更优雅的方式将回调链接在一起?完成后,我可以看到自己需要做更多的清理代码,所以我必须做一个不同的done延迟,并让当前doneDF触发一个回调,然后调用done延迟的东西。

4

3 回答 3

6

啊,真正的答案是使用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()
于 2010-09-15T20:32:21.640 回答
5

deferToThread您可以通过使用而不是callInThread/callFromThread对来简化这一点:

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

deferToThread基本上只是一个很好的包装器,它与您在您的函数版本中实现了两次相同的线程逻辑。

于 2010-08-11T22:23:47.183 回答
0

如果程序在您关闭反应器后终止,您可以使线程成为守护线程。当所有非守护线程终止时,这将自动退出。只需daemon = True在调用 start() 之前设置线程对象。

如果这不可行,例如线程必须在退出之前进行资源清理,那么您可以使用队列在反应器和线程之间进行通信。将要完成的工作推送到 Queue 对象上,并让线程将其拉出并执行。有一个特殊的“FINISH”标记(或简单的无)来指示线程需要终止。

于 2010-08-11T20:55:38.753 回答