我有一个正在后台运行的线程,可以从主线程进行更新:
import threading
from Queue import Queue
from time import sleep
class Animation(threading.Thread):
SIGNAL_STOP = 'stop'
def __init__(self, framerate):
threading.Thread.__init__(self)
self.queue = Queue()
self.framerate = framerate
def tell(self, data):
self.queue.put(data)
def stop(self):
self.tell(Animation.SIGNAL_STOP)
def loop(self):
# Override this method to implement animation loop
pass
def update(self, data):
# Override this method to implement the state update
pass
def cleanup(self):
# Override this method to implement what's done when the animation is stopped
pass
def run(self):
while True:
if not self.queue.empty():
data = self.queue.get()
if data == Animation.SIGNAL_STOP:
break;
self.update(data)
self.loop()
sleep(1. / self.framerate)
self.cleanup()
class TestAnimation(Animation):
def __init__(self, framerate):
super(TestAnimation, self).__init__(framerate)
self.num = 0
def loop(self):
print 'num =', self.num
self.num = self.num + 1
def update(self, data):
print 'update:', data
def cleanup(self):
print 'graceful exit'
print 'start'
ta = TestAnimation(1)
ta.start()
sleep(3)
ta.update(123)
sleep(3)
#ta.stop() # I'd like the animation thread to feel that the parent wants to exit and carry out stopping itself
print 'end'
exit()
我想实现某种方法来检测父线程何时要退出,然后所有正在运行的线程将正常终止。我宁愿代替显式调用运行线程的stop()方法。
答案 0 :(得分:1)
我相信您可以将其设置为daemon线程,因此当主线程退出时,所有守护线程都随之退出。
因此,您可以在构造函数中将其默认设置为daemon = True
,也可以将其设置为start
之前
ta = TestAnimation(1)
ta.daemon = True
ta.start()
您可以使用thread.Event
和atexit
的组合来发信号通知守护程序线程,以在退出之前进行清理。
这是一个简单的示例:
import time
import threading
import atexit
signal_to_threads = threading.Event() # Global signal for threads to stop.
registered_threads = [] # Register all threads into here.
@atexit.register
def signal_threads():
print('signaling threads to stop')
signal_to_threads.set()
for thread in registered_threads:
thread.signal.wait()
class TestExit(threading.Thread):
def __init__(self, *args, **kw):
registered_threads.append(self)
self.signal = threading.Event()
super(TestExit, self).__init__(*args, **kw)
self.daemon = True # Ensure is a daemon thread.
def run(self):
while True:
time.sleep(3)
print('Hi from child thread')
if signal_to_threads.is_set():
print('stopping child thread and doing cleanup.')
# self.do_cleanup()
self.signal.set()
break
t = TestExit()
t.start()
print('sleeping for 10 secs.')
time.sleep(10)
print('exiting main thread')
python test_thread.py
sleeping for 10 secs.
Hi from child thread
Hi from child thread
Hi from child thread
exiting main thread
signaling threads to stop
Hi from child thread
stopping child thread and doing clean up.
由于atexit
应该在退出时运行已注册的函数,因此无需紧跟每个退出点来清理线程。