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()
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?
------------------------------------------------------------------------
_______________________________________________
pygtk mailing list [email protected]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/
_______________________________________________ pygtk mailing list [email protected] http://www.daa.com.au/mailman/listinfo/pygtk Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/
