扭曲线程中的完全阻塞生成器,永远运行

时间:2016-09-15 10:52:07

标签: python multithreading twisted

假设我们有一个 blackbox 生成器,它完全阻塞并永远运行。我们正在运行Twisted,因此处理阻止内容的标准方法是使用Formattersdefers

defers + threads

耶!工作完成了! ......但不完全是。

在我们想要停止整个Twisted应用程序之前,一切都很棒。其中一个关闭步骤是调用类似〜# some very naive example from twisted.internet import reactor def aSillyBlockingMethod(): for results in fullblocking_blockbox_generator_that_runs_forever(): print results reactor.callInThread(aSillyBlockingMethod) reactor.run() 的东西,它等待所有线程完成自己。但不是我们的完整的以太网 blackbox 生成器。我们不能在循环中做很多事情,因为我们需要从发生器中得到永远不会发生的结果。

我浏览整个互联网的想法。没有。也许我错过了一些重要的事情,或者有一种聪明的方法可以解决这个问题?

1 个答案:

答案 0 :(得分:0)

我接受了this post提供的答案并添加了示例代码。另外请记住,最好为线程定义明确的起点和终点。正如您所看到的,如果线程以不受控制的方式永远运行,它可能会导致一些非常棘手的情况。话虽如此,有时某些情况是不可避免的(但这并不意味着我们不应该尽可能避免它。)

如果 blackbox 不需要Twisted中的任何内容,您可以将其作为Twisted控件之外的守护程序线程启动,该程序将在您的应用程序停止时停止。一般来说,这是非常危险,因为这会立即杀死线程,这可能会使事情处于损坏状态。无论如何,这是一个例子:

from threading import Thread, Event
from time import sleep
from twisted.internet import reactor

class BlackBox(Thread):

    def __init__(self, stop_event=None):
        super(BlackBox, self).__init__()
        if not stop_event:
            stop_event = Event()
        self.stop_event = stop_event

    def run(self):
        while True:
            print('running in thread')
            if self.stop_event.is_set():
                print('STOPPING!')
                break
            sleep(1)

t = BlackBox()
t.daemon = True
t.start()
# reactor.callLater(5, t.stop_event.set)      # if you want to stop thread after 5 seconds
reactor.run()

更好的选项是在线程代码中有一个控制流,例如检查Event,并在应用关闭时启动触发器。要在Twisted中捕获此类触发器,请使用reactor.addSystemEventTrigger

from threading import Event
from time import sleep
from twisted.internet import reactor

def aSillyBlockingMethod(event):
    while True:
        print('running in thread')
        if event.is_set():
            print('STOPPING')
            break
        sleep(1)

stop_event = Event()
reactor.callInThread(aSillyBlockingMethod, stop_event)
reactor.addSystemEventTrigger('before', 'shutdown', stop_event.set)
reactor.run()

选项#2是比守护程序线程更好的解决方案,因为线程代码不会随意停止,您可以让Twisted管理线程,并且线程可以在适当的时间停止(由开发人员认为)。我希望这有帮助