David E. Konerding DSD staff wrote: [...] > You need another way to pass completion information between the downloader > thread and the main thread; the simplest way is to define a custom wx > Event, and wxPostEvent from the downloader thread when it completes ( > and when the gauge should be updated). wxPostEvent is safe to call from non-eventloop threads. > The main thread's wx event loop just spins, properly updating all other > parts of the GUI, and receiving events from the downloader thread. > > ANother approach is to have a thread-safe Queue and have the main thread/event loop > poll the queue with queue.get_nowait() periodically (typically 0.1-1 sec). > The downloader thread shares the queue object and puts data structures (typically > class instances, strings, or ints) that indicate status updates.
The way-cool things to transmit, in either the queue or the event data, are tuples of: (func, args, kwargs) The so-called-'main' thread gets these, and blindly calls func(*args, **kwargs). Since only the main thread can safely update the GUI, other threads pass GUI-updating functions to be called by the main thread. The technique is beautifully general. The worker thread does it's long, blocking operations independently, and when it needs to update the GUI it sends the main thread a quick, non-blocking function. In wxPython, custom events can carry arbitrary data, so the easy thing to do is just pass the (func, args, kwargs) across with wxPostEvent (or so I've read; I'm not a wxPython user). TkInter has no equivalent to wxPostEvent. Contrary to popular belief, TkInter's event_generate is not thread-safe. The usual TkInter solution is a queue, which the main thread periodically polls via the 'after' function. > The easiest approach, though, is to use the threadedselectreactor in Twisted (you need > to check the HEAD branch out with subversion, because that reactor isn't included in any releases). > With threadedselectreactor, it's easy to incorporate both the GUI event loop and the twisted reactor. > Twisted already includes lots of code for doing asynchronous callback-style IO for > IO bound processes like downloading. Further, you don't even think in an explicitly threaded way- > createing a whole thread just to manage a download process which is motly IO and a little bookkeeping is > silly. Twisted's approach just makes a lot more sense and simplifies the code too. I couldn't disagree more about that being easier and simplifying the code. "Creating a whole thread" is trivial. -- --Bryan -- http://mail.python.org/mailman/listinfo/python-list