Passing multiple values to a Thread

Hi.
Like a lot of people, I seem to be stuck on threading.

I have an app which retrieves multiple forms of user input
(wxTextCtrl, wxChoice, etc.)
This data is then crunched by a function. Being a newbie GUI
programmer, I didn't realize this would block the application's GUI
when a time-consuming function was called.

I did some research, and found out I probably needed threading. After
working through some examples, I tried to apply threading to my
application.
Unfortunately, I wasn't able to figure out how to pass the variables
containing user input to the new, data-crunching thread. I don't know
if I'm looking at it the wrong way, or if I completely missed
something.

Could someone try to specify and specific terms when/where I pass
multiple variables (can also be another data-type) containing the user
input to the new thread?

Thanks,
Daniel

I think this is probably the best all-encompassing article on wxPython and threads: http://wiki.wxpython.org/LongRunningTasks and this is a simple one: http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/

When I start a new thread, I have always passed the information needed to it when I create the thread. Then I start the thread. If you need to actually send it additional data, then you’ll probably need to read the Python documentation on the Threading module. Once you’ve passed the info and the thread finishes crunching the data, it can then tell the GUI to update using wx.CallAfter or wx.PostEvent.

···

Mike Driscoll

Blog: http://blog.pythonlibrary.org

Here's a simple script that demonstrates creating a standard Python
thread, passing it arguments, blocking on it, and getting a return
value via a queue:

import Queue
import threading

def crunch(a, b, c, resultQueue):
    resultQueue.put((a * b) + c)

resultQueue = Queue.Queue()
thread = threading.Thread(target = crunch, args = [3, 5, 7, resultQueue])
thread.start()
thread.join()
print resultQueue.get()

Since you don't want to have your main thread block while the
data-cruncher runs, instead of having the "thread.join()" call (which
will block on the thread completion) and the queue, you can do
something like this instead at the end of crunch():

wx.CallAfter(processResult, (a * b) + c)

where processResult is another function, accepting one argument in this case.

Hope that helps.

-Chris

···

On Thu, Sep 8, 2011 at 2:20 PM, Daniel Fontaine <danielfontaine10@gmail.com> wrote:

I did some research, and found out I probably needed threading. After
working through some examples, I tried to apply threading to my
application.
Unfortunately, I wasn't able to figure out how to pass the variables
containing user input to the new, data-crunching thread. I don't know
if I'm looking at it the wrong way, or if I completely missed
something.

A common pattern for doing this is a command queue. Basically you have a queue object that the gui thread will add command objects to. Those commands can be anything that is able to carry the information that you want to be able to pass to the worker thread. Typically they would be instances of some Command class that is specific to your application's needs but really anything will work. When you create the worker thread you give it a reference to that queue and it starts a loop that reads the next command object from the queue, performs the command (whatever it may be) and then does something with the results. (You could even do something like have one of the attributes in the command object be a function that should be called when the command is completed.) Since Python's queue.Queue class is thread safe and will block in get() by default if there are no items waiting in the queue yet then it is perfect for implementing this pattern. You can also have more than one instance of the worker thread processing items in the queue if needed.

Remember that anything that interacts with the GUI needs to be done in the GUI thread, so you'll need to ensure that the results of the worker(s) is passed to the GUI thread first before they are displayed in the GUI. wx.CallAfter has a convenient side-effect that it is thread-safe and will always call the function you pass it in the UI thread as soon as any current and pending events are processed.

···

On 9/8/11 2:20 PM, Daniel Fontaine wrote:

Hi.
Like a lot of people, I seem to be stuck on threading.

I have an app which retrieves multiple forms of user input
(wxTextCtrl, wxChoice, etc.)
This data is then crunched by a function. Being a newbie GUI
programmer, I didn't realize this would block the application's GUI
when a time-consuming function was called.

I did some research, and found out I probably needed threading. After
working through some examples, I tried to apply threading to my
application.
Unfortunately, I wasn't able to figure out how to pass the variables
containing user input to the new, data-crunching thread. I don't know
if I'm looking at it the wrong way, or if I completely missed
something.

Could someone try to specify and specific terms when/where I pass
multiple variables (can also be another data-type) containing the user
input to the new thread?

--
Robin Dunn
Software Craftsman