【问题标题】:How to end threads when closing window in wxpython在wxpython中关闭窗口时如何结束线程
【发布时间】:2012-09-12 20:21:11
【问题描述】:

我正在尝试使用 wxPy 构建一个 GUI 应用程序,以执行一些长脚本操作。我已将 GUI 和脚本放在不同的线程中以防止阻塞。这工作得很好,除了在我关闭 GUI 之后,包含脚本的线程仍然在运行。

以下是我的程序的简化版本(对不起,如果代码难以理解或缺少部分,我在缩短程序方面很糟糕)

class Form(wx.Frame):
    ...
    def test(self, evt):
        t2 = threading.Thread(target = self.runTest)
        t2.start()
    def runTest(self):
       result = really_long_script()

def main():
   app = wx.App(False)
   form = form(app)
   app.MainLoop()

t1 = threading.Thread(target = main)
t1.start()

有什么方法可以杀死线程吗?现在,当我关闭窗口时,脚本仍在后台运行。

任何帮助将不胜感激!

谢谢,

约翰

【问题讨论】:

  • 正如我所提到的,脚本很长而且有很多,所以如果可能的话,我不想定期检查结束标志。我希望有一个更简单的解决方案。
  • 抱歉,没有看到解决方案的第二部分。它似乎停止了线程,但目前 self.Destroy 冻结了应用程序。希望我能解决这个问题。非常感谢!

标签: python multithreading wxpython


【解决方案1】:

如果你将线程设置为守护线程,它会和主线程一起死掉。

您可以通过在调用 start 之前添加行 t2.daemon = True 来做到这一点

编辑: 看看这个例子,当你关闭框架时,t.daemon = True 行线程会死掉,如果你注释掉 t.daemon = True 行,框架关闭后线程会保持活动状态

import wx
import time
from threading import Thread

def print_something_forever(something):
    while True:
        print something
        time.sleep(1)

class Frame(wx.Frame):
    def __init__(self,parent):
        wx.Frame.__init__(self,parent)
        self.panel= wx.Panel(self)
        t= Thread(target=print_something_forever,args=("Thread alive!",))
        t.daemon= True
        t.start()
        self.Show()

if __name__ == "__main__":
    app= wx.App(False)
    Frame(None)
    app.MainLoop()

【讨论】:

  • 我将所有线程设置为守护进程,但在我关闭窗口后它们继续运行。谢谢你这么快回答。
  • 嗯。我刚刚注意到在你的例子中你线程main() 函数。这不需要线程化,可能会导致问题。此外,只有在所有帧都已关闭时,主循环才会退出,这将结束主线程。你确定你周围没有框架(也许是没有 .Show 调用它们的隐形框架?)
  • 我从线程中取出了 main ,但这并没有做任何事情。我在程序中只有一帧,所以我不应该有任何不可见的帧。但是,由于我对编程还很陌生,所以我可能会遗漏一些明显的东西。关闭框架的正确方法是什么?另外,当我使用 Hide() 时,它会删除项目吗?例如: x = wx.Panel(frame, ...) x.Hide() x = wx.Panel(frame, ...) 这会是个问题吗?
  • 上面的例子对你有用吗?也许您可以从中建立起来,直到遇到问题为止。我只是用关闭的十字从gui关闭它,但是如果你需要从代码中关闭它,你可以调用.Close()或者更强大的.Destroy(),两者都是框架的方法
  • 上面的例子似乎没有用,它一直在打印 'Thread alive!'在我关闭窗口后
【解决方案2】:

Python 不支持杀死/销毁线程,可能是因为内存泄漏、资源丢失等原因。

试试这个“线程化类”:D

class Run_Other_Thread(threading.Thread):
      "Raises a child thread \
       I'm busy dying, rather lying - _P0W !"
      def __init__(self,func_name,*args): #Constructor
            self._func=func_name
            self._func_args=args
            threading.Thread.__init__(self)
      def run(self): # Start Dying
            try:
                print("\n** Running New Thread :"+self._func.func_name)
            except:
                print("\n** Running New Thread :"+self._func.__name__)
            self._func(*self._func_args)
      def stop(self):
            print('!! Stopped')
      def __del__(self):#Constructor
            try:
                print('\n  @@ Farewell :'+self._func.func_name)
            except:
                print('\n  @@ Farewell :'+self._func.__name__)

您可以将 GUI 运行为:(并尝试关闭)

def GUI():
    app= wx.App(False)
    Frame(None)
    app.MainLoop()

if __name__ == '__main__':
      "Tkinter GUI in Thread helps in De-bugging"
      Run_Other_Thread(GUI).start() # Release command window control

【讨论】:

  • 太棒了!没有更多的崩溃......写MainLoopAsThread页面的人应该只是指向这里。他们的代码实际上无法在不崩溃的情况下关闭。我希望将此与Radek's 方法一起用于从主线程发送消息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多