从菜单栏中退出Tkinter应用程序 - 无法杀死线程

时间:2014-05-08 22:31:14

标签: python tkinter

我有一个带有Tkinter GUI的Python应用程序。在应用程序中,用户调用长时间运行的后台进程(从Python的Thread模块实现为threading)。如果我在程序完成之前退出程序,我在查看后台线程时遇到问题。 如果我通过顶角的“X”关闭根窗口退出应用程序,我的代码可以正常工作,但如果我退出顶级菜单栏(即Python>退出或Ctrl + Q)则不行/ strong>即可。由于大多数应用程序使用后者,我真的很想做到这一点。

现在,我使用如下代码终止后台线程:

class BackgroundCallFrame(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.background_call = BackgroundCall()
        self.background_call.start()

class BackgroundCall(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self._stop_req = threading.Event()

    def run(self):
        for i in range(1,100000):
            if self._stop_req.is_set():
                return
            else:
                # do stuff

    def stop(self):
        self._stop_req.set();

def main():

    def kill_all_threads():
        if child.background_call is not None:
           child.background_call.stop()
           child.background_call.join()
        root.destroy()

    root = Tk()
    root.wm_protocol ("WM_DELETE_WINDOW", kill_all_threads)

    child = BackgroundCallFrame()
    child.pack()
    root.mainloop()

if __name__ == '__main__':
    main()

如果我在没有先明确关闭根窗口的情况下退出程序,我该如何才能完成这项工作?

我相信我的问题是当我调用Ctrl + Q时没有调用kill_all_threads(),因为我添加到它的任何打印语句都不会出现在控制台中。

1 个答案:

答案 0 :(得分:0)

通常你会希望通过在该线程中设置一个变量来杀死一个线程,以表示它停止工作。在线程的run方法中,您需要定期检查该变量以了解何时退出run方法。这是一个例子......

import threading
import time

class WorkerThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.do_stop = False

    def run(self):
        while True:
            time.sleep(.5)

            print 'I am running'

            if self.do_stop:
                return # exit loop and function thus exiting thread

t = WorkerThread()
t.start()

time.sleep(4) # sleep while our thread runs and prints to the command line

print 'setting do_stop to True'
t.do_stop = True # signal to thread to stop

t.join() # wait for thread to exit

print 'all done'

...输出...

I am running
I am running
I am running
I am running
I am running
I am running
I am running
setting do_stop to True
I am running
all done