2

我正在尝试创建一个线程,并在 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()

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

4

2 回答 2

6

没有什么神奇的Frame.OnExit方法。您正在混淆框架和应用程序。与其他窗口一样,框架会关闭。应用程序退出。

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

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

你总是可以绑定EVT_CLOSE在你的窗口中调用你想要的任何东西。但是你必须明确地这样做。

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

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

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

这是有关绑定的教程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 时,您的代码不可能发生这种情况——但您可以证明(或至少确定安全的情况),不要指望它。


最后,您询问了守护线程是否是合适的解决方案。从文档

这个标志的意义在于,当只剩下守护线程时,整个 Python 程序就退出了。

换句话说,您的程序可以退出而无需停止您的守护线程。但是……</p>

注意 守护程序线程在关闭时突然停止。它们的资源(如打开的文件、数据库事务等)可能无法正常释放。如果您希望线程优雅地停止,请将它们设为非守护进程并使用合适的信号机制,例如Event.

于 2013-03-13T04:21:50.897 回答
1

尝试设置tickThread.setDaemon(True)之前tickThread.start()-守护线程应该与它们的父线程一起退出。

于 2013-03-13T04:16:39.580 回答