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.)