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