wxPython OnExit()没有停止线程?

tkb*_*kbx 2 python multithreading wxpython

我正在尝试创建一个线程,并在关闭wxPython应用程序的框架时结束它.这是我的代码:

#! /usr/bin/env python

import time, wx
from threading import Thread

class UpdateThread(Thread):
    def __init__(self):
        self.stopped = False
        Thread.__init__(self)
    def run(self):
        while not self.stopped:
            self.updateExchange()
            time.sleep(1)
    def updateExchange(self):
        print("Updated...")

class tradeWindow(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, "Exchange", size = (500, 190))
        panel = wx.Panel(self)
    def OnExit(self):
        tickThread.stopped # I've also tried: tickThread.stopped = True

tickThread = UpdateThread()
tickThread.start()
if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = tradeWindow(parent = None, id = -1)
    frame.Show()
    app.MainLoop()
Run Code Online (Sandbox Code Playgroud)

但是当我关闭框架时,它会继续打印.

aba*_*ert 6

没有神奇的Frame.OnExit方法.你正在混合框架和应用程序.框架,像其他窗户一样,关闭.应用退出.

因此,您可以将代码放在app类的OnExit方法中.但这不是你想要的.

看看这个简单的教程OnExit方法.同样,这不是你想要的,但你应该知道它是如何工作的(以及它被调用的对象).

您始终可以绑定EVT_CLOSE以在窗口中调用任何所需内容.但你必须明确地这样做.

通常,你会调用方法OnCloseOnCloseWindow.调用它OnExit只会导致严重的混乱(因为它).

绑定到的事件处理程序方法实际上必须是一个事件处理程序,这意味着它需要一个event参数(以及self).

接下来,如果添加EVT_CLOSE处理程序,则覆盖默认处理程序,这意味着Destroy除非您自己执行,否则永远不会调用它.

这是一个关于绑定的教程EVT_CLOSE,它显示了上述所有步骤.

最后,正如大卫罗宾逊所解释的那样,做tickThread.stopped就不会做任何事情; 你必须把它设置为True.

把它们放在一起:

class tradeWindow(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, "Exchange", size = (500, 190))
        panel = wx.Panel(self)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
    def OnClose(self, event):
        tickThread.stopped = True
        self.Destroy()
Run Code Online (Sandbox Code Playgroud)

还有一点说明:

在任何严重的线程程序中,如果要在线程之间共享值,通常需要将其与某种同步对象同步.如果您正在等待来自另一个线程的信号,那么处理该信号的典型方法是使用Condition.另一方面,如果您只想分享价值,可以使用Lock.

如果您真的知道自己在做什么,通常可以让Global Interpreter Lock为您处理同步.但总的来说,这是一个坏主意.例如,您的主线程可以在核心0上运行,而后台线程可以在核心1上运行,并且Python语言定义中没有任何内容可以保证计算机将更新的值从核心0的缓存复制到核心1.因此,您的后台线程可能会永远旋转,观察旧值并永远不会看到新值.事实证明,在x86上使用CPython 2.0-3.3时,你的代码不可能发生这种情况 - 但是你可以证明(或者至少确定安全的情况),不要指望它.


最后,您询问守护程序线程是否是合适的解决方案.来自文档:

这个标志的意义在于,当只剩下守护进程线程时,整个Python程序都会退出.

换句话说,您的程序可以在不必停止守护程序线程的情况下退出.但…

注意守护程序线程在关闭时突然停止.他们的资源(例如打开文件,数据库事务等)可能无法正确发布.如果您希望线程正常停止,请使它们成为非守护进程并使用合适的信令机制,例如Event.