python - wxPython OnExit() 不停止线程?

标签 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()

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

最佳答案

没有神奇的 Frame.OnExit 方法。你混淆了框架和应用程序。像其他窗口一样,框架关闭。应用退出。

因此,您可以将代码放入应用类的 OnExit 方法中。但这不是您想要的。

this simple tutorial对于 OnExit 方法。同样,这不是您想要的,但您应该知道它是如何工作的(以及它被调用的对象)。

您始终可以绑定(bind) EVT_CLOSE 以在您的窗口中调用您想要的任何内容。但是你必须明确地这样做。

通常,您会调用方法 OnCloseOnCloseWindow。称它为 OnExit 只会导致严重的困惑(因为它已经发生了)。

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

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

这是 a tutorial关于绑定(bind) EVT_CLOSE,它显示了上述所有步骤。

最后,正如 DavidRobinson 解释的那样,仅仅执行 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()

再补充一点:

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

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


最后,您询问守护线程是否是合适的解决方案。来自 the docs :

The significance of this flag is that the entire Python program exits when only daemon threads are left.

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

Note Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.

关于python - wxPython OnExit() 不停止线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15376787/

相关文章:

java - 防止线程子类等待

python - wxPython 内部 : two created threads after calling app. MainLoop()

python - matplotlib 为二元矩阵着色

python - 我可以在 Python doctest 的行首使用省略号吗?

multithreading - 线程池、线程安全队列、OOP

c# - 处理 ErrorDataReceived 时出现 NullReferenceException - 终止线程

python - wx.ListBox 中具有多个选择的 CTRL 键单击行为

python - 树莓派到 AB controllogix : how to trigger output in GPIO based on continuosly reading plc tag value

python - for循环在python中包含或排他

python - len(sys.argv) 中的语法错误