Greg Lee | 7 Jun 2005 04:30

tkinter and threading

Are Tkinter callbacks run in separate threads?  Do I need to use threading locks to protect data shared
between callbacks that can run at the same time? I'm running Python 2.3 and Tkinter on Windows.

I have two callbacks: cb_close and cb_run.  cb_close cleans up, then uses Tkinter.Toplevel.destroy; it is
bound to WM_DELETE_WINDOW via Tkinter.Toplevel.protocol.

cb_run uses a COM component to perform a lengthy operation.  The COM component calls back to the Python world
often enough that I can keep my GUI responsive using Tkinter.Toplevel.update.

Bad things happen if I allow cb_close to call destroy while cb_run is in progress: cb_run eventually asks
the Tkinter world to post a completion dialog.  To keep this from happening I use a state variable to tell
cb_close that it should not call destroy if cb_run is in progress and to tell cb_run that it should not
execute if a cb_close is in progress.

I can definitely get cb_close to run at the same time as cb_run, which suggests that the Tkinter eventloop
executes its callbacks in separate threads.  All this lead me to use a lock to protect read/write of the
state variable.  Was this necessary?  Is there something in the way that Tkinter handles callbacks that
automatically protects shared data structures?

--------------------------------------------
Greg Lee / Pharsight Corporation / Suite 200
800 W El Camino / Mountain View CA 94040
voice: 650-314-3860 / fax: 650-314-3810

This email message (including any attachments) 
is for the sole use of the intended recipient 
and may contain confidential  and proprietary
information.  Any disclosure or distribution 
to third parties that is not specifically 
authorized by the sender is prohibited.  
(Continue reading)

Jeff Epler | 7 Jun 2005 15:57
Favicon

Re: tkinter and threading

No, Tkinter callbacks are not run in separate threads.

When you see cb_close being called during cb_run, it's all in a single
thread, with a call stack that looks like
    cb_close    
    update
    cb_run
    mainloop
i.e., when cb_run calls update, events (including "the user clicked a
button", "pressed a key", etc.) are handled, leading to this effect.

You may be able to use update_idletasks instead of update.  They have
different semantics as to which events they handle.  update_idletasks
should let things like resizing and repainting windows work, while
delaying the response to user actions like clicking until an update or a
return to the mainloop.

I've included a copy of the update manpage below.  Tcl's "update" command is
the .update() method, and "update idletasks" is the .update_idletasks() method.

Jeff

update(n)                    Tcl Built-In Commands                   update(n)

______________________________________________________________________________

NAME
       update - Process pending events and idle callbacks

SYNOPSIS
(Continue reading)


Gmane