On Thu, 2005-27-10 at 14:06 +0200, Antoon Pardon wrote: > I have written a small gtk threading tutorial with a number > of demo's and an (IMO) helpfull module. I don't fancy > myself to be a good writer, but I thought the demo's > would make up for that. Let me know what you think. > > http://www.pardon-sleeuwaegen.be/antoon/python/page0.html >
That is a nice tutorial. I have not had a chance to study it in detail, but from looking at your iotube.py and idletube.py scripts I think they might be more complex than needed. I will study it more later. Attached is the dispatcher.py script that another developer on our project came up with and I tweaked a little and has been working very good for us. The dispatcher instance can be based from any thread and allows a queue'd set of data arguments to be passed back to it without collision. It is also very generic and most any python data types can be passed thru it. -- Brian <[EMAIL PROTECTED]>
#! /usr/bin/env python # Fredrik Arnerup <[EMAIL PROTECTED]>, 2004-12-19 # Brian Dolbec<[EMAIL PROTECTED]>,2005-3-30 import gobject, os, Queue from select import select class Dispatcher: """Send signals from a thread to another thread through a pipe in a thread-safe manner""" def __init__(self, callback_func, *args, **kwargs): self.callback = callback_func self.callback_args = args self.callback_kwargs = kwargs self.continue_io_watch = True self.queue = Queue.Queue(0) # thread safe queue self.pipe_r, self.pipe_w = os.pipe() gobject.io_add_watch(self.pipe_r, gobject.IO_IN, self.on_data) def __call__(self, *args): """Emit signal from thread""" self.queue.put(args) # write to pipe afterwards os.write(self.pipe_w, "X") def on_data(self, source, cb_condition): if select([self.pipe_r],[],[], 0)[0] and os.read(self.pipe_r,1): if self.callback_args: args = self.callback_args + self.queue.get() self.callback(*args, **self.callback_kwargs) else: self.callback(*self.queue.get(), **self.callback_kwargs) return self.continue_io_watch
#! /usr/bin/env python # Fredrik Arnerup <[EMAIL PROTECTED]>, 2004-12-19 # Brian Dolbec<[EMAIL PROTECTED]>,2005-3-30 from dispatcher import Dispatcher # #################################### # dispatcher # example code: # # # #################################### class Thread(threading.Thread): def __init__(self, dispatcher, thread_num, length): threading.Thread.__init__(self) self.setDaemon(1) # quit even if this thread is still running self.dispatcher = dispatcher self.thread_num = thread_num self.sleep_length = length def run(self): done = False print("thread_num = %s; process id = %d ****************" %(self.thread_num,os.getpid())) pid_func(self.thread_num) for num in range(250): #print self.thread_num, " num = ",num #sleep(self.sleep_length) data = [ self.thread_num, (": time is slipping away: %d\n" %num), num, done] self.dispatcher(data) # signal main thread done = True data = [ self.thread_num, (": Time slipped away: I'm done"), num, done] self.dispatcher(data) # signal main thread def pid_func(threadnum): print("pid_func: called from thread_num = %s; process id = %d ****************" %(threadnum,os.getpid())) def message_fun(buffer, message): #print ("got a message : %s" %(message[0] + str(message[1]))) if message[3]: thread_finished[message[0]] = True buffer.insert(buffer.get_end_iter(), message[0] + str(message[1]) + "\n\n") else: #message2 = ("%d x 3 = %d\n" %(message[2],message[2]*3)) buffer.insert(buffer.get_end_iter(), message[0] + str(message[1])) # + message2) return def timerfunc(): if (not thread_finished["thread1"]) or (not thread_finished["thread2"]) \ or (not thread_finished["thread3"]) or (not thread_finished["thread4"]): pbar.pulse() #print 'Plusing ProgressBar, since a thread is not finished' return True else: pbar.set_fraction(0) pbar.set_text("Done") return False def on_window_map_event(event, param): print 'Window mapped' thread1 = Thread(Dispatcher(message_fun, buffer), "thread1", 0.1) thread2 = Thread(Dispatcher(message_fun, buffer), "thread2", 0.1) thread3 = Thread(Dispatcher(message_fun, buffer), "thread3", 0.1) thread4 = Thread(Dispatcher(message_fun, buffer), "thread4", 0.1) gobject.timeout_add(100, timerfunc) thread1.start() thread2.start() thread3.start() thread4.start() if __name__ == "__main__": import pygtk; pygtk.require("2.0") import gtk from time import sleep gtk.threads_init() window = gtk.Window(gtk.WINDOW_TOPLEVEL) textview = gtk.TextView() buffer = textview.get_buffer() sw = gtk.ScrolledWindow() sw.add(textview) pbar = gtk.ProgressBar() vbox = gtk.VBox() vbox.pack_start(sw) vbox.pack_start(pbar, False) window.add(vbox) #gui_dispatcher = Dispatcher(message_fun, buffer) window.connect('map_event', on_window_map_event) window.connect("destroy", gtk.main_quit) window.resize(400, 600) window.show_all() thread_finished = {"thread1":False, "thread2":False, "thread3":False, "thread4":False} gtk.threads_enter() gtk.main() gtk.threads_leave()
_______________________________________________ pygtk mailing list pygtk@daa.com.au http://www.daa.com.au/mailman/listinfo/pygtk Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/