I am working on a GUI app with python v2.7 and wxPython 3.0 on windows 7 OS. I have a general question regarding threads. In my programm I am creating a thread that will update my GUI continuously. If I close the GUI window it seems that everything is closed and is fine. How ever upon executing my code from command prompt I observed that the thread keeps sending updates to the GUI.
Question: Since my GUI is updating properly and even closes without any crashes should I bother about the thread that is still working hard to update my GUI after I have closed the GUI window? If this is a very serious concern?
It would be great if someone can suggest that how can I can modify my closeWindow()
so that when the GUI is closed, it first kills the thread.
Code: Here is a sample code. Please execute the code from console/cmd then you'll notice my problem.
import wx
from wx.lib.pubsub import setupkwargs
from wx.lib.pubsub import pub
import time
from threading import Thread
class GUI(wx.Frame):
def __init__(self, parent, id, title):
screenWidth = 500
screenHeight = 400
screenSize = (screenWidth,screenHeight)
wx.Frame.__init__(self, None, id, title, size=screenSize)
self.locationFont = locationFont = wx.Font(12, wx.MODERN, wx.NORMAL, wx.BOLD)
mainSizer = wx.BoxSizer(wx.VERTICAL)
myPanelA = wx.Panel(self, style=wx.SIMPLE_BORDER)
myPanelA.SetBackgroundColour('#C0FAE0')
self.myTextA = wx.StaticText(myPanelA, -1, "Testing")
mainSizer.Add(myPanelA, 1, wx.EXPAND, 5)
self.SetSizer(mainSizer)
self.Bind(wx.EVT_CLOSE, self.closeWindow)
pub.subscribe(self.updatePanelA, 'Update-panelA')
def updatePanelA(self, message):
self.myTextA.SetLabel(message)
def closeWindow(self, event):
# --> Code for killing the thread :)
self.Destroy()
class threadA(Thread):
def __init__(self):
Thread.__init__(self)
self.start()
def run(self):
ObjA = updateGUI()
ObjA.methodA()
class updateGUI():
def methodA(self):
while True:
time.sleep(2)
print 'Sending update'
wx.CallAfter(pub.sendMessage, 'Update-panelA', message='Yes, It works')
if __name__=='__main__':
app = wx.App()
frame = GUI(parent=None, id=-1, title="Problem Demo-PSS")
frame.Show()
threadA()
app.MainLoop()
Thank you for your time and any help will be appreciated.
Alright, the way it was is not ok, the thread was left alive continually sending updates to a GUI that didn't exist. This caused it to throw a nasty error about the C++ bit not being real or some such nonsense. But you can avoid this pretty easily by making the following changes:
__init__()
method and create it as a class attributecloseWindow()
method of your GUI unsubscribe itself from the thread (to protect against transmission after closingrunning
)while
loop in the thread to be based off the new running
parameter so it can be told when to stopapp
to not have redirect (app = wx.App(False)
)Take all of that into account and you're left with the following code:
import wx
from wx.lib.pubsub import setupkwargs
from wx.lib.pubsub import pub
import time
import threading
class GUI(wx.Frame):
def __init__(self, parent, id, title):
screenWidth = 500
screenHeight = 400
screenSize = (screenWidth,screenHeight)
wx.Frame.__init__(self, None, id, title, size=screenSize)
self.locationFont = locationFont = wx.Font(12, wx.MODERN, wx.NORMAL, wx.BOLD)
mainSizer = wx.BoxSizer(wx.VERTICAL)
myPanelA = wx.Panel(self, style=wx.SIMPLE_BORDER)
myPanelA.SetBackgroundColour('#C0FAE0')
self.myTextA = wx.StaticText(myPanelA, -1, "Testing")
mainSizer.Add(myPanelA, 1, wx.EXPAND, 5)
self.SetSizer(mainSizer)
self.Bind(wx.EVT_CLOSE, self.closeWindow)
pub.subscribe(self.updatePanelA, 'Update-panelA')
self.thd = threadA()
def updatePanelA(self, message):
self.myTextA.SetLabel(message)
def closeWindow(self, event):
# --> Code for killing the thread :)
pub.unsubscribe(self.updatePanelA, 'Update-panelA')
self.thd.running = False
self.Destroy()
class threadA(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
self.running = True
self.start()
def run(self):
while self.running:
time.sleep(2)
print 'Sending update'
wx.CallAfter(pub.sendMessage, 'Update-panelA', message='Yes, It works')
if __name__=='__main__':
app = wx.App(False)
frame = GUI(parent=None, id=-1, title="Problem Demo-PSS")
frame.Show()
app.MainLoop()
Hope this helps