调用event.set()后不通知threading.Event()。wait()

时间:2014-03-23 04:29:24

标签: python python-multithreading

使用threading.Event()时我遇到了一个非常奇怪的问题,并且无法理解发生了什么?我一定错过了什么,请你指出来吗?

我有一个Listener类,它与信号处理程序共享相同的事件对象,这是我的简化代码:

import threading, time

class Listener(object):    

    def __init__(self, event):        
        super(Listener, self).__init__()
        self.event = event

    def start(self):                
        while not self.event.is_set():            
            print("Listener started, waiting for messages ...")    
            self.event.wait()

        print("Listener is terminated ...")
        self.event.clear()    

event = threading.Event()

def handler(signum, frame):    
    global event
    event.set()
    print('Signal handler called with signal [%s]' % signum)

if __name__ == "__main__": 
    signal.signal(signal.SIGINT, handler)
    listener = Listener(event)
    listener.start()

运行代码后,按ctrl + c中断它,实际上什么也没发生。如果我想退出,我必须使用kill -9来杀死进程。但是,如果我向event.wait()提供一个参数,它就可以了。但它一直打印出来:

  

听众启动,等待消息......"

每次都是秒。但它会打印出来:

  

听众被终止......

按Ctrl + c这就是我想要的。

while not self.event.is_set():
        print("Listener started, waiting for messages ...")
        self.event.wait(1)

为什么我必须在event.wait()中给出超时参数以使其响应ctrl + c事件?根据文档http://docs.python.org/2/library/threading.html#event-objects,一旦标志为真,调用wait()的event.wait()线程将不会阻塞。我顺便使用python 2.7.3。

3 个答案:

答案 0 :(得分:2)

这对你有用吗?基本上,为Listener启动另一个线程,并在主线程等待信号时等待。

#!/usr/bin/python
import threading, signal

class Listener(threading.Thread):
    def __init__(self, event):
        super(Listener, self).__init__()
        self.event = event

    def run(self):
        while not self.event.is_set():                                                                                                                                            
            print("Listener started, waiting for messages ...")
            self.event.wait()

        print("Listener is terminated ...")
        self.event.clear()

event = threading.Event()

def handler(signum, frame):
    global event
    event.set()
    print('Signal handler called with signal [%s]' % signum)

if __name__ == "__main__":
    signal.signal(signal.SIGINT, handler)
    listener = Listener(event)
    listener.start()
    while listener.is_alive():
        pass 

答案 1 :(得分:1)

有几个线程讨论python的线程,中断,锁,事件的相关问题。

例如,请参阅herehere,但还有更多内容。

在python3中情况要好得多,wait()的实现得到了改进,使其不会中断。

答案 2 :(得分:0)

以下代码与原始代码类似。

的差异:

  1. 继承Thread类,使用run(vs start)

  2. 使用简单的wait(),没有超时,这是更可预测的

  3. 信号处理程序不会直接触发Event。相反,它只是隐含地唤醒了主要流程,该流程位于signal.pause()

  4. 主要触发器Event.set()pause()唤醒后触发SIGINT - 主过程将在任何信号上执行此操作,而不只是import signal, threading, time class Listener(threading.Thread): def __init__(self, event): super(Listener, self).__init__() self.event = event def run(self): print("Listener started, waiting for messages ...") while not self.event.wait(): print('(timeout)') print("Listener is terminated ...") self.event.clear() event = threading.Event() def handler(signum, _frame): # global event # event.set() print('Signal handler called with signal [%s]' % signum) if __name__ == "__main__": signal.signal(signal.SIGINT, handler) signal.signal(signal.SIGALRM, handler) signal.alarm(2) listener = Listener(event) listener.start() print '* PAUSE' signal.pause() # wait for a signal print '* SIGNALLING' event.set() listener.join() print('* DONE') (控制-C)。出于测试目的,两秒钟后会有一个报警电话。

  5. 希望这有帮助!

    Listener started, waiting for messages ...
    * PAUSE
    Signal handler called with signal [14]
    * SIGNALLING
    Listener is terminated ...
    * DONE
    

    输出

    {{1}}