On Wed, 2005-03-30 at 19:54 -0800, John Finlay wrote:
> L�szl� Monda wrote:
> 
> >On Sat, 2005-03-26 at 08:04 -0500, John (J5) Palmieri wrote: 
> >  
> >
> >>On Sat, 2005-03-26 at 06:46 -0600, Skip Montanaro wrote:
> >>    
> >>
> >>>    L�szl�> I want to make my application very responsive under high load.
> >>>    ...
> >>>    L�szl�> As you can see, I want to pulse a progress bar while a long
> >>>    L�szl�> (computationally or I/O intensive) operation is running.  I
> >>>    L�szl�> started a separate thread for it.
> >>>
> >>>I could be wrong (never used threads with gtk), but don't you have some 
> >>>sort
> >>>of gtk thread initialization function(s) to call?  See if something in
> >>>section 20 of the PyGTK FAQ leads to a solution:
> >>>
> >>>    http://www.async.com.br/faq/pygtk/index.py?req=index
> >>>      
> >>>
> >>gtk.gdk.threads_init()
> >>
> >>also you can update the progress bar from you thread by calling these
> >>two methods to lock the main thread:
> >> 
> >>gtk.gdk.threads_enter()
> >><gui update code here>
> >>gtk.gdk.threads_leave()
> >>
> >>    
> >>
> >
> >Thanks everyone for the help.  In this particular example, it was enough
> >to call gtk.threads_init() before gtk.main() to work properly.
> >
> >However according to the PyGTK documentation, timeout handlers are
> >outside the GDK global lock and therefore every GTK functions should be
> >wrapped in gtk.threads_enter() and gtk.threads_leave() inside them.
> >
> >Is it possible that gtk.threads_init() was enough in this example
> >because the other thread didn't do any GUI manipulation?
> >
> >
> >Beyond that there are some things I cannot completely understand from
> >the documentation:
> >
> >1) Why should I use gtk.threads_enter() and gtk.threads_leave() around
> >gtk.main()?  I would suppose that this locks the main thread and doesn't
> >let other threads running.  I tried it and know that it doesn't, but
> >it's still illogical to me.
> >
> >2) Are the gtk.threads_*() functions the same as the gtk.gdk.threads_*()
> >functions?  In my experience they are, but I couldn't find any related
> >documentations.
> >
> >
> >Unfortunately my real world application still doesn't work because it
> >manipulates the GUI in more thread, so I've written a second test
> >application to demonstrate the problem in a more deep but (hopefully)
> >still clear way (also attached in pygtk-threading-example-2-wrong.py):
> >
> >#!/usr/bin/env python
> >
> >import threading
> >import signal
> >import gtk
> >
> >def timerfunc():
> >    if not thread_finished:
> >        gtk.threads_enter()
> >        pbar.pulse()
> >     print 'Plusing ProgressBar, since '+ \
> >         'thread_finished is'+`thread_finished`
> >        gtk.threads_leave()
> >    return not thread_finished
> >
> >def threadfunc():
> >    for i in range(25):
> >     k = 0
> >     for j in range(1000000):
> >         k += 1
> >
> >        string = 'foo '+`i`
> >        print 'Appending to TreeView "'+string+'"'
> >        gtk.threads_enter()
> >        store.append([string])
> >     gtk.threads_leave()
> >    thread_finished = True
> >    print 'thread_finished is True'
> >
> >def on_window_map_event(event, param):
> >    print 'Window mapped'
> >    while gtk.events_pending():
> >        gtk.main_iteration(False)
> >    thread_finished = False
> >    gtk.timeout_add(50, timerfunc)
> >    thread = threading.Thread(target=threadfunc)
> >    thread.run()
> >  
> >
> Try thread.start() instead of thread.run()

Ouch!  I'm banging my head against the wall.  Thanks John!

> >store = gtk.ListStore(str)
> >renderer = gtk.CellRendererText()
> >column = gtk.TreeViewColumn('Foos', renderer, text=0)
> >view = gtk.TreeView(store)
> >view.append_column(column)
> >sw = gtk.ScrolledWindow()
> >sw.add(view)
> >pbar = gtk.ProgressBar()
> >vbox = gtk.VBox()
> >vbox.pack_start(sw)
> >vbox.pack_start(pbar, False)
> >window = gtk.Window()
> >window.set_default_size(100, 600)
> >window.add(vbox)
> >window.show_all()
> >window.connect('map_event', on_window_map_event)
> >window.connect('destroy', gtk.main_quit)
> >
> >signal.signal(signal.SIGINT, signal.SIG_DFL)
> >gtk.threads_init()
> >gtk.threads_enter()
> >gtk.main()
> >gtk.threads_leave()
> >
> >There is a window which contains a TreeView (above) and a ProgressBar
> >(below).  When the window gets mapped, it shows up (just because
> >gtk.main_iteration(False) got called).  At this point the timer and the
> >new thread begins to run.  The timer should pluse the ProgressBar in
> >every 50 msec and the new thread should call a computationally intensive
> >code 25 times and add a new line to the TreeView each time.  I'd expect
> >them to run simultaneously, but the application freezes here.
> >
> >The output looks like this:
> >
> >Window mapped
> >Appending to TreeView "foo 0"
> >
> >I don't know why because I guarded GTK calls with gtk.threads_enter()
> >and gtk.threads_leave() in the new thread as well as in the timer
> >function as described the documentation.
> >
> >I've tried various combinations of the issues 1) and 2) I mentioned
> >above and experimented with several things with no success at all.
> >
> >I'd gladly contribute to some parts of the documentation if I'd know
> >more details on this issue.
> >
> >Could anyone shed some lights on what's really going on here?

Well, problem solved, great.  There were some minor errors in the code
beyond thread.start().  I corrected them all and attached the source.

It would make a nice threading example IMO.  I don't remember any
examples where more than one thread would manipulate the GUI
simultaneously.  Someone could add it to some parts of the documentation
or should I contact with a documentation manintainer?

-- 
L�szl� Monda  <http://mondalaci.objectis.net>

Attachment: pygtk-threading-example-2-right.py
Description: application/python

_______________________________________________
pygtk mailing list   [email protected]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to