1

Relative newcomer to wxPython and threading, hence confusion.

I have 5 "steps" that must be performed on my target data. The steps must be performed sequentially in a given order.

In order to keep the GUI responsive, I've coded each step as an individual thread.

When I step through the process manually (using a button to start each step) I can watch each step update the display when finished.

I'm lost as to how to automate the calling of each of the threads sequentially. If I were to create a button labeled "Do all 5 steps in a row", what would the code called by the button look like?

I've tried simply calling each of the threaded methods sequentially, but they all attempt to operate on the data at once. Each thread uses a 'with' and a threading.Lock() to prevent other threads from accessing the data while a given thread is running, but the threads do not appear to be executing in the correct order.

What is the proper way to write

call_thread1()
call_thread2()
call_thread3()
..etc.

that will always execute the threads in the given order and only after each thread is done without blocking wx?

1
  • There is also very convenient library for starting threads in wx called wx.lib.delayedresult. Function startWorker takes two parameters, worker thread function and consumer function which is called after the worker one finished.
    – Fenikso
    Commented Nov 28, 2013 at 9:20

2 Answers 2

2

Have a waiting step member of your gui as a list and a thread finished handler that if there is a next task pops it off the list and starts the thread.

In __init__(self) :

   self.TaskList = []

In OnDoAllClicked(self, evt):

   self.TaskList.extend([call_thread1, call_thread2, call_thread3, etc])
   CheckNextTask()

In CheckNextTask(self) :

   if len(self.TaskList) > 0:
      current = self.TaskList[0]
      del self.TaskList[0]
      current(callback=self.CheckNextTask)

In each thread:

   while not Done:
      # Do whatever
   wx.CallAfter(callbacK)
2
  • That's what I have in mind, but how do I code it? How do I elegantly tell the GUI "wait here until the last thread is finished, but still handle your GUI stuff in your normal loop? A while loop with a wx.Yield(), time.sleep() inside it?
    – JS.
    Commented Nov 26, 2013 at 22:24
  • Example code added above - you could even enable all buttons at the start of CheckNextTask and disable the appropriate button at the start of each call_thread Commented Nov 27, 2013 at 20:11
2

I think I would go with a different approach. I would call a single thread that has each of the five functions in it. Then that thread can call each function in order and when each function returns, it can send an update to the GUI using one of the GUI's thread-safe methods (wx.CallAfter, wx.PostEvent).

Here are a couple of resources for more information regarding wxPython and threads:

2
  • 1
    That's a good idea...might be the way I wind up doing it. Occasionally I want to do a few other things in the middle before calling the next thread... or call one thread out of order, though.
    – JS.
    Commented Nov 26, 2013 at 22:22
  • 1
    I'm sure you could do that with a couple of optional parameters or possibly a list of the options in the order that you want to do them in. Commented Nov 26, 2013 at 22:29

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.