1

I have a wxPython gui that is controlling some hardware. I need a button to disable while a function is running. The function also receives an argument value

let's say that I have this function that is bound to a button press:

    def button_press(self, event):

       in_val = self.num_in.GetValue() #grabs a value from a NumCtrl
       TheThread(in_val) #initiates the thread with argument
       btn = event.GetEventObject() 
       btn.Disable() #disables button

this function goes to the following thread class:

    class TheThread(Thread):
def __init__(self, in_val):

    """Init Worker Thread Class."""
    Thread.__init__(self)

    self.run(in_val)

def run(self, in_val):
    print val
    time.sleep(5)

    wx.CallAfter(Publisher.sendMessage, "ctrl")
    """
    threadsafe method to call a pub.subscribe that runs a 
    function to re-enable button
    """

This works improperly, as the gui freezes during the function run period, and the button does not properly disable.

How do I properly inherit this argument to allow this to run properly? Maybe something involving self.start() method?

2 Answers 2

2

You're right in your guess about the start method.

run is the method that gets invoked on the new thread, and start is the method you want to call to tell the Thread object to do that.

In your example, by calling run yourself you're calling run on the main thread and no threading is taking place at all. (the thread is never started)

class TheThread(Thread):
    def __init__(self, in_val):

        """Init Worker Thread Class."""
        Thread.__init__(self)

        self.in_val = in_val
        self.start()

    def run(self):
        print self.in_val
        time.sleep(5)

        wx.CallAfter(Publisher.sendMessage, "ctrl")
        """
        threadsafe method to call a pub.subscribe that runs a 
        function to re-enable button
        """
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! So I guess in the case of threading, you don't pass the argument value through to the next function, but instead pass it as a self.var to the function? is there a reason for this?
@supremus_58 right, the run method doesn't take any arguments itself. However if you pass a target function instead you can provide arguments as well, and the default Thread.run method will invoke the target callable with the arguments you provide. t = Thread(target=my_func, args=("arg1", "arg2"), kwargs={"kwarg1":"val"}) t.start()
0

Don't call run() from __init__(). run() sleeps for 5 seconds and then returns. But __init__() needs to return before the object is fully instantiated, and the calling code blocks until __init__() returns. It is the same situation for most function calls, i.e. the calling code waits for the function to return (or yield in the case of a generator) before continuing execution.

To correct this problem remove the call to run() from __init__() and call the start() method on the TheThread() instance:

def button_press(self, event):
    in_val = self.num_in.GetValue()
    TheThread(in_val).start()
    btn = event.GetEventObject() 
    btn.Disable() #disables button

class TheThread(Thread):
    def __init__(self, in_val):
        """Init Worker Thread Class."""
        super(TheThread, self).__init__()
        self.in_val = in_val

    def run(self):
        print self.in_val
        time.sleep(5)
        wx.CallAfter(Publisher.sendMessage, "ctrl")

You could also call the thread's start() method within __init__(), however, the more common way is to call start on the thread instance itself. This is a more flexible solution because the thread can be created first and then started later, e.g. if you had a pool of threads in which all threads are created first and then started together.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.