管理线程中的事件循环

时间:2013-09-05 15:18:45

标签: python multithreading

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

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

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

3 个答案:

答案 0 :(得分:1)

您的想法是正确的(请参阅this documentation中的说明)使用标记,但不能使用内部daemon属性作为标记,因为它将返回错误。

Python中的

Documentation

  
    

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

  

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

答案 1 :(得分:1)

  • 使用控制生命周期的条件变量

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

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

答案 2 :(得分: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):
    ...

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