Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
wxPython OnExit()不停止线程?_Python_Multithreading_Wxpython - Fatal编程技术网

wxPython OnExit()不停止线程?

wxPython OnExit()不停止线程?,python,multithreading,wxpython,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):

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

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

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

没有神奇的
frame.OnExit
方法。你把框架和应用程序搞混了。与其他窗口一样,框架也会关闭。应用程序退出

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

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

您始终可以绑定
EVT\u CLOSE
在窗口中调用任何您想要的内容。但你必须明确地做到这一点

通常,您会调用方法
OnClose
OnCloseWindow
。将其称为OnExit只会导致严重的混乱(正如它所做的那样)

绑定到的事件处理程序方法实际上必须是一个事件处理程序,这意味着它接受一个
事件
参数(以及
自身

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

下面是关于binding
EVT\u 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()

另请注意:

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

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


最后,您询问了守护进程线程是否是合适的解决方案。发件人:

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

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

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


tickThread.stopped=True
显然更接近解决方案(
tickThread.stopped
永远不会做任何事情)。你试过在
OnExit
中放一个打印语句以确保它被调用吗?@DavidRobinson它没有被调用,很奇怪……我必须检查一下,但我认为
wx.Frame
没有
OnExit
;这是
wx.App
。根据一些谷歌搜索,我认为你的
\uuuu init\uuuuuu
中缺少了一行:
self.Bind(wx.EVT\u CLOSE,self.OnExit)
(请在我作为答案发布之前试一试)@DavidRobinson我在
\uu init\uuuuuu
的末尾添加了这句话,当我按下关闭按钮时,我得到了
TypeError:OnExit()正好接受1个参数(给定2个)
。我给OnExit()添加了一个无用的参数,现在它运行OnExit()函数,但不关闭窗口。到目前为止,它似乎很完美,但有什么缺点吗?@tkbx:如果你想完全关闭,你不能这样做。如果你不在乎清洁关机,这是一个简单的解决办法。@abarnert“清洁关机”到底是什么意思?
OnClose
方法手动处理所有事情,而不是将工作传递给Python?@tkbx:Daemon线程没有完全关闭,它们只是在某个任意点停止运行。如果您想确保它们已经完成,或者释放一些系统资源,或者刷新对文本文件或数据库的写入,这样它们就不会丢失,那么您不能这样做。阅读中的第一个注释。另外,您确实不应该调用
setDaemon
。这在2.x中是“旧的”,在3.x中是“不推荐的”。正如文档所说,只需直接设置
守护进程
属性。