chow
chow

Reputation: 484

Calling a Class function from another Class

My limitations are my worst enemy, but bestest learning buddy.

I have two classes:

class WorkerThread(Thread):
"""Worker Thread Class."""
def __init__(self, notify_window):
    """Init Worker Thread Class."""
    Thread.__init__(self)
    self._notify_window = notify_window
    self.ToKill = False
    self._want_abort = 0
    self.start()

def run(self):
    """Run Worker Thread."""
    while worker==True:
        # somehow get to volumePanel.startStop() 

        if self.ToKill == True:
            return None
    proc.wait()
    wx.PostEvent(self._notify_window, ResultEvent(None))
    return

And:

class VolumePanel(wx.Panel):
    #<...snip...>
    def launchVolClick(self, event):
        if self.bt_Launch.Label == "Enable Monitor":
            self.worker = WorkerThread(self)
            self.bt_Launch.Label = "Disable Monitor"
        else:
            self.worker.ToKill = True
            self.bt_Launch.Label = "Enable Monitor"

    def startStop(self):
        print "in def startStop()"

I want to find a way to call startStop from within the WorkerThread. I've tried this and couldn't get it to work either.

EDIT: Final working code below

class WorkerThread(Thread):
    """Worker Thread Class."""
    def __init__(self, notify_window, func):
        """Init Worker Thread Class."""
        Thread.__init__(self)
        self._notify_window = notify_window
        self.ToKill = False
        self._want_abort = 0
        global function
        function = func
        self.start()

    def run(self):
        """Run Worker Thread."""
        while worker==True:
            # somehow get to volumePanel.startStop() 
            function()
            if self.ToKill == True:
                return None
        proc.wait()
        wx.PostEvent(self._notify_window, ResultEvent(None))
        return

    def launchVolClick(self, event):
        if self.bt_Launch.Label == "Enable Volume Monitor":
            self.worker = WorkerThread(self, self.startStop)
            self.bt_Launch.Label = "Disable Volume Monitor"
        else:
            self.worker.ToKill = True
            self.bt_Launch.Label = "Enable Volume Monitor"

Upvotes: 0

Views: 2306

Answers (2)

10se1ucgo
10se1ucgo

Reputation: 71

You can also passs the calling class to the thread like so:

class WorkerThread(threading.Thread):
    def __init__(self, parent):
        super(WorkerThread, self).__init__()
        self.parent = parent

    def run(self):
        for i in range(10):
            wx.CallAfter(self.parent.startStop)


class VolumePanel(object):
    def startStop(self):
        print "in def startStop()"

Notice that we use wx.CallAfter() instead of just calling the function directly. This is because if we call it directly, it's actually being called from the thread instead of the MainThread. This can sometimes be a problem depending on whatever you're doing.

If we print out the current thread (with threading.current_thread()) without wx.CallAfter, we get

<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>
<WorkerThread(Thread-1, started 6612)>

However, with wx.CallAfter, we get

<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>
<_MainThread(MainThread, started 6604)>

Upvotes: 0

Pythonista
Pythonista

Reputation: 11615

You could pass a reference to startStop and call the reference from within the thread class as one option. Without seeing more code / how your code is structured it's hard to say for other options.

Here's a contrived example of the former. You don't have to pass things around this way you could call the thread in VolumePanel and pass self.startStop.

Also, worker is undefined and so is proc unless this if some part of wxpython which I'm not familiar with.

from threading import Thread

class WorkerThread(Thread):

    def __init__(self, func):

        Thread.__init__(self)
        self.func = func

    def run(self):

        for i in range(10):
            self.func()

class VolumePanel:

    def __init__(self):

        #self.thread = WorkerThread(self.startStop)
        #self.thread.start() #or elsewhere
        pass

    def startStop(self):

        print "in def startStop()"

vp = VolumePanel()
thread = WorkerThread(vp.startStop)
thread.start()

Upvotes: 1

Related Questions