Multi-platform Threading

Eric Brunel eric.brunel at pragmadev.N0SP4M.com
Mon Oct 20 10:30:47 CEST 2003


Peter Hansen wrote:
> Lane LiaBraaten wrote:
> 
>>>Are you using the proper mechanisms provided by Tkinter to communicate
>>>with the GUI thread?
>>
>>I have no idea.  What proper mechanisms are you refering to?  All I know is
>>that the program works on Linux and not on WinNT.  Are there and glaring
>>differences that I should be aware of?
> 
> 
> I don't use Tkinter, so I can't tell you about differences, but if I'm
> right about the fundamental nature of the problem, the fact that it works
> on one platform and not the other is incidental: it could just as well
> have been the other way around, or it might even be intermittent on 
> one or both platforms and you just haven't noticed it yet.
> 
> If this is, for example, due to a classic race condition, you could run
> your Linux program for days without seeing the problem, then suddenly
> see it "for no good reason at all", then not again for weeks.
> 
> I could be way off base.  That's why I asked.  The fact that you 
> didn't say something like "I'm no rookie, sport: of course I didn't 
> screw up the GUI thread" suggests I might be on to something. ;-)
> 
> In general, GUI frameworks don't deal well with multiple threads,
> except through tightly controlled interfaces which generally (a)
> defer handling certain external events until an appropriate time,
> and (b) temporarily suspend regular event processing and GUI
> work such as redrawing while handling the external event at the
> later time.  
> 
> From the wxPython demo, for example:
> 
>  '''The main issue with multi-threaded GUI programming is the thread 
>   safety of the GUI itself.  On most platforms the GUI is not thread 
>   safe and so any cross platform GUI Toolkit and applications written 
>   with it need to take that into account.
> 
>   The solution is to only allow interaction with the GUI from a single
>   thread, but this often severly limits what can be done in an
>   application and makes it difficult to use additional threads at all.
> 
>   Since wxPython already makes extensive use of event handlers, it is a
>   logical extension to allow events to be sent to GUI objects from
>   alternate threads.  A function called wxPostEvent allows you to do
>   this.  It accepts an event and an event handler (window) and instead
>   of sending the event immediately in the current context like
>   ProcessEvent does, it processes it later from the context of the GUI
>   thread.'''
> 
> I'm sure Tkinter has similar restrictions, and solutions.

It does have both: Tkinter should be used only in its own thread and everything 
coming from other threads can be processed using the method event_generate 
available on all Tkinter widgets with user-defined events.

For example:
-----------------------------------------------
import threading, time
from Tkinter import *

root = Tk()

def ping():
   while 1:
     time.sleep(1)
     root.event_generate('<<Ping>>', when='tail')

v = BooleanVar()
v.set(0)
Checkbutton(root, variable=v, text='Ping!').pack(side=TOP)
Button(root, text='Quit', command=root.quit).pack(side=TOP)

def gotPing(event):
   v.set(not v.get())

root.bind('<<Ping>>', gotPing)

th = threading.Thread(target=ping)
th.setDaemon(1)
th.start()

root.mainloop()
-----------------------------------------------

Every time the thread has to do something with Tkinter, it generates a <<Ping>> 
event that is caught by Tkinter's thread, which actually does the processing.

NB: always use event_generate(..., when='tail'). If you don't specify a when 
option, the binding is called immediatly in the current thread's context, which 
is not what you want.

HTH
-- 
- Eric Brunel <eric dot brunel at pragmadev dot com> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com





More information about the Python-list mailing list