Question

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.

Était-ce utile?

La solution

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:

  1. Create the thread within the GUI's __init__() method and create it as a class attribute
  2. Have the closeWindow() method of your GUI unsubscribe itself from the thread (to protect against transmission after closing
  3. Signal the thread to stop transmitting by altering a parameter I added (running)
  4. Create the thread as a daemon
  5. Modify the while loop in the thread to be based off the new running parameter so it can be told when to stop
  6. Tell app 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

Autres conseils

Your 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 IS VERY SERIOUS CONCERN.

Some threads can be out there just to provide "computational resources outside the main thread", however many (if not most) times threads are used to access system resources such as sockets, serial ports, etc.

In these cases, the resource has been opened by and is solely owned by the thread, so any other process requiring that resource can't get it, and possibly more importantly, if you rerun your program again, it won't work, because the prior thread owns the resource you need.

Learn to use your OS's thread viewers (and thread-killing routines). You will need them. Then write your own programs so that you will not need them (by proper thread control).

Hi mate check out the solution given to killing threads in this post Terminate python threads using sys.exit()

I hope it can help you solve your problem :)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top