0

我正在编写一个具有事件处理循环的库中的类:

class EventSystem(object):

    def __init__(self):
        self.queue = Queue.Queue()
        self.thread = threading.Thread(target=self_process_loop)
        self.thread.daemon = True
        self.thread.start()

    def _process_loop(self):
        while True:
            event = self.queue.get()
            self._handle_event(event)

    def _handle_event(self, event):
        ...

我已将线程设置为线程,daemon因此它与主程序一起退出,但这意味着它可能会在处理过程中被杀死。我真的很想在它被杀死之前等待当前的处理迭代完成。

通常在这些情况下,在 while 循环中会检查一个标志,并且有一些方法 -stop()比如说 - 设置它False。如果可能的话,我宁愿避免这个要求。

以下被认为是坏的吗?

    def _process_loop(self):
        while True:
            event = self.queue.get()
            self.thread.daemon = False
            self._handle_event(event)
            self.thread.daemon = True

编辑:是的,这很糟糕:RuntimeError: cannot set daemon status of active thread

实现这一目标的正确方法是什么?

4

3 回答 3

1

您的想法是正确的,您应该(请参阅本文档中的注释)使用标志,但是您不能将内部daemon属性用作标志,因为它会返回错误。

Python 中的文档:

daemon
一个布尔值,指示此线程是否为守护线程 (True) 或不是 (False)。这必须在调用 start() 之前设置,否则会引发 RuntimeError。它的初始值继承自创建线程;主线程不是守护线程,因此在主线程中创建的所有线程默认为 daemon = False。

所以你应该创建另一个变量作为标志。

于 2013-09-05T15:35:44.937 回答
1
  • 使用控制生命周期的条件变量

  • 捕捉“杀死”你的守护进程的信号

  • 每当信号发生时,设置终止条件,以便守护程序在处理完所有事件后退出

于 2013-09-05T15:40:12.223 回答
0

从 umläute 的回答(孩子从父线程接收信息的想法)继续,我意识到我可以监控父线程的状态。

使线程非守护进程消除了它退出中间处理的问题。然后检查父线程以查看它是否仍在运行我可以干净地退出:

class EventSystem(object):

    def __init__(self):
        self.queue = Queue.Queue()
    self.parent_thread = threading.current_thread()          # <-- Added
    self.thread = threading.Thread(target=self_process_loop)
    self.thread.start()

def _process_loop(self):
    while self.parent_thread.is_alive():                    # <-- Changed
        try:
            event = self.queue.get(timeout=1)               # <-- Timeout added
        except Queue.Empty:
            continue
        else:
            self._handle_event(event)

def _handle_event(self, event):
    ...

这引入了轮询,但它是一个可行的解决方案,它不需要客户端加入或停止后台线程。

于 2013-09-05T18:35:47.493 回答