[Tutor] Illegal Operation??

D-Man dsh8290@rit.edu
Thu, 31 May 2001 10:26:29 -0400


On Thu, May 31, 2001 at 07:08:18PM +1000, Glen Wheeler wrote:
| > I'm afraid Tcl/Tk doesn't play nice with threads.  For example, the usual
| > result of trying to run a threaded program under IDLE is also some sort of
| > crash in tcl83.dll.  AFAIK, the only way to get it to work is to write
| your
| > code such that *you* guarantee that the thread in which Tk is first
| invoked
| > is the *only* thread Tk ever gets invoked from or gets called back from.
| > For example, do all your computation in one thread and all your GUI in a
| > different thread.
| >
| 
|   ARGH....seriosuly?  *sneaks a side look at 1200+ line script in question*.
| 
|   Oh dear.  Allow me some time to grieve.
| 
| ...
| 
|   Ok, over it...  So, it should be fine if I keep all the gui stuff in one
| thread...and all the other stuff in other threadS?  I will need more than
| two...and here I was thinking I was finished.
|   Perhaps the lockups aren't random, but where GUI calls are made to
| tcl...hmmm there may be a pattern.  There is a pattern!  Brilliant, now if I
| just grow an extra day, I can get this finished on time.
|   Argh...perhaps two days...why doesn't tcl just work with threads?  :(
| 
|   *gets ready for an all-niter*

It's really not that unusual -- neither GTK+ nor Swing are
thread-safe.  Swing, however, provides 3 methods that are extrememly
useful for threaded applications :

http://java.sun.com/products/jdk/1.2/docs/api/javax/swing/SwingUtilities.html#isEventDispatchThread()

http://java.sun.com/products/jdk/1.2/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)

http://java.sun.com/products/jdk/1.2/docs/api/javax/swing/SwingUtilities.html#invokeAndWait(java.lang.Runnable)


In Swing there is a thread (named AWTEvent_Queue) that handles all
user interaction.  It is in this thread (or the 'main' thread if a
single-threaded app) that all GUI operations must occur.  (Any
operation on a not-yet-visible and
no-visible-widget-has-a-reference-to-it widget is fine because no
events will happen from the AWTEvent_Queue thread)

The standard Java idiom for allowing threads to interact with swing is
:


Runnable r = new Runnable()
    {
        public void run()
        {
            // this would really contain the code to tinker with the
            // GUI
            System.out.println( "I am tinkering with the GUI now" ) ;
        }
    } ;

if ( javax.swing.SwingUtitilies.isEventDispatchThread() )
{
    r.run() ;
}
else
{
    javax.swing.SwingUtitilies.invokeLater( r ) ;
}



A "Runnable" in Java is like a "callable object" in Python except it
can't return any object.  The SwingUtilities class has synchronized
access to the GUI event thread so it can append any callable
(Runnable) object to the event queue.  When it gets to the front of
the queue it is run by the event thread.  The only problem is if this
code is already in the event dispatch thread -- it will sit in
deadlock waiting until it is finished to continue.  Thus the
isEventDispatchThread() query -- if this is the event thread just run
the code now.

You should be able to create such utility functions for Tkinter and
replace all GUI interaction code with the above blocks (without the
excess braces, etc).

HTH,
-D