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/

Reply via email to