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()
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?
--
L�szl� Monda <http://mondalaci.objectis.net>
pygtk-threading-example-2-wrong.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/
