A method that is often mentioned is defering the gtk call to the main thread. In general what this means is that in threads instead of calling a gtk/gdk call directly, you inbed it in a gobject.idle_add call. The working threads then become something like the following. (A full demo implementing this idea can be found in demo3a.py.)
class Counting (Thread): def __init__(self, Id) def run(self): while ...: Calculate Results gob.idle_add(canvas.Adjust, self.Id, self.ShowTime , self.ShowValue) def Start_Stop(self,ignore) def Modus(self,ignore): if Running: Change Mode else: Reset Values gob.idle_add(canvas.Adjust, self.Id, self.Time , self.Value) def Quit(self): Make thread leave loop
However what we have here is essentially an unbounded Queue. That may work in a lot of cases but again in our demo the working threads produce more results than the gtk thread can process, So we get very sluggisch and erratic behaviour (even had a crash) .
The next solution I propose is a tube. A tube is a Queue like object but with important differences that make it more usefull in the gtk environment.
So first we need a function that will get an element from the tube and process it, This fuction will be registered later, Something like:
def Draw(): try: Id, ShowTime, ShowValue = Tube.get() canvas.Adjust(Id, ShowTime , ShowValue) except EOInformation: gtk.main_quit()
The working threads are like in the Queue example except for the opening of the Tube in the beginning and the absence of gtk lock calls.
class Counting (Thread): def __init__(self, Id) def run(self): Tube.open("r") while ...: Calculate Results Tube.put((self.Id, self.ShowTime , self.ShowValue)) def Start_Stop(self,ignore) def Modus(self,ignore): if Running: Change Mode else: Reset Values Tube.put((self.Id, self.ShowTime , self.ShowValue)) def Quit(self): Make thread leave loop
The only thing left is for the gtk-thread to open the tube and register it before starting. This would do it.
Tube.open("rw") tube_add_watch(Tube, Draw) gtk.main()
There are two implementations for the tube module iotube.py. and idletube.py. The demo demonstrating this idea is demo3b.py.)