如何在框架关闭时终止或杀死python GUI应用程序中的子线程
Posted
技术标签:
【中文标题】如何在框架关闭时终止或杀死python GUI应用程序中的子线程【英文标题】:how to terminate or kill child thread in python GUI application on frame close 【发布时间】:2015-11-26 19:08:31 【问题描述】:我使用 wx.Python 编写了一个 python GUI 应用程序 在下面的代码中,它在单击主框架中的开始按钮时会执行什么操作,它将在单独的线程中启动一个框架(MyForm),并在其中打印一些文本。我需要的是,在关闭 MyForm 框架时,当前子线程执行应该终止或终止,并且控制应该回到主线程。我在一个模块中编写的所有代码
import wx, wx.html
from threading import Thread
import wx
import control
import sys
class Frame(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self, None, -1, 'Sample frame', size=(750, 350))
self.panel = wx.Panel(self, -1)
'''
button <start> to start the script
'''
self.button_start = wx.Button(self.panel,-1,"Start",pos=(100,220),size=(100,40))
self.button_close = wx.Button(self.panel,-1,"Close",pos=(300,220),size=(100,40))
self.Bind(wx.EVT_BUTTON,self.click_start,self.button_start)
self.Bind(wx.EVT_BUTTON, self.OnClose,self.button_close)
def click_start (self,event):
self.MyTask()
def MyTask(self):
step_a = 1
step_b = 50
self.frame2 = MyForm().Show()
TestingThread(step_a, step_b)
def OnCloseWindow(self,event):
self.Close(True)
def OnClose(self, event):
dlg = wx.MessageDialog(self,
"Do you really want to close this application?",
"Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
result = dlg.ShowModal()
dlg.Destroy()
if result == wx.ID_OK:
self.Destroy()
class App(wx.App):
def __init__(self, redirect=True, filename=None):
wx.App.__init__(self, redirect, filename)
def OnInit(self):
self.frame = Frame(parent=None, id=-1) #Create Frame
self.frame.Show()
return True
def OnExit(self):
self.Exit()
class TestingThread(Thread):
"""Test Worker Thread Class."""
def __init__(self,a, b):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.a = a
self.b = b
self.start()
def run(self):
self.res=control.main(self.a, self.b)
class RedirectText(object):
def __init__(self,aWxTextCtrl):
self.out=aWxTextCtrl
def write(self,string):
self.out.WriteText(string)
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "wxPython Log Redirect Box",size= (500,300))
self.Bind(wx.EVT_CLOSE, self.OnClose)
panel = wx.Panel(self, wx.ID_ANY)
log = wx.TextCtrl(panel, wx.ID_ANY, size=(500,300),
style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL|wx.TE_NOHIDESEL)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(log, 1, wx.ALL|wx.EXPAND, 5)
panel.SetSizer(sizer)
# redirect text here
redir=RedirectText(log)
sys.stdout=redir
def OnClose(self, event):
dlg = wx.MessageDialog(self,
"Do you really want to close this application?",
"Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
result = dlg.ShowModal()
dlg.Destroy()
if result == wx.ID_OK:
self.Destroy()
self.MakeModal(False)
if __name__ == '__main__':
app = App(redirect=False)
app.MainLoo
【问题讨论】:
您使用什么操作系统?如果它的窗口,在 Python 中没有办法真正杀死一个线程,只有进程可以被“杀死”。如果是 Linux,情况就不同了——这里的线程可以被杀死。 我正在使用 Windows。你能告诉我如何改变我的代码来处理流程吗? 【参考方案1】:当您使用 Windows 时,Python 无法在线程未终止时实际“杀死”线程。如何解决这个问题有很多可能性。 例如:
与线程通信并告诉它停止 将“worker”作为外部进程运行(例如使用 popen) 使用 multiprocessing.Process这是最后一个示例。请注意,您需要使用 multiprocessing.Queue 或 IPC 功能(例如 Pyro4)才能与进程通信。
from multiprocessing import Process
import time
import wx
procs = []
def subproc():
while True:
print("Hello World")
time.sleep(1)
def OnStart(event):
myProc = Process(target=subproc)
myProc.start()
print("Started new process with PID ".format(myProc.pid))
procs.append(myProc)
def OnStop(event):
for proc in procs:
proc.terminate()
if __name__ == '__main__':
app = wx.App()
frame = wx.Frame(None, -1)
frame.Show()
sizer = wx.BoxSizer(wx.HORIZONTAL)
btn1 = wx.Button(frame, -1, "Start")
btn2 = wx.Button(frame, -1, "Stop")
sizer.Add(btn1, 0)
sizer.Add(btn2, 1)
frame.SetSizer(sizer)
frame.Fit()
frame.Layout()
frame.Bind(wx.EVT_BUTTON, OnStart, id = btn1.GetId())
frame.Bind(wx.EVT_BUTTON, OnStop, id = btn2.GetId())
app.MainLoop()
【讨论】:
以上是关于如何在框架关闭时终止或杀死python GUI应用程序中的子线程的主要内容,如果未能解决你的问题,请参考以下文章
即使应用程序处于终止状态或被杀死,如何在 iOS 中获取位置更新? [复制]
将用户位置发送到服务器(Web文件)甚至应用程序已关闭或终止或终止iOS Swift