More on Tk event_generate and threads

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Dale Huffman

    #1

    More on Tk event_generate and threads

    There have been a number of posts about calling gui methods from other
    threads. Eric Brunel. has reccommended calling the gui's
    ..event_generat e method with data passed thru a queue. This worked
    great for me until trying to write to the gui from multiple threads.
    There I had problems: random typesof crashes almost all resulting in
    seg faults. I thought this info might help anyone trying to do the
    sameor at least save some time debugging.

    I wrote a (hopefully) simple and minimal piece of code to demonstrate
    the problem included below. My knowledge of the Tcl/Tk interface is
    minimal.

    Another interesting thing is it fails on some systems and not on
    others. All Linux:

    Runs fine on:
    Dual Opteron Fedora5
    Linux xxxx 2.6.16-1.2096_FC5 #1 SMP Wed Apr 19 05:14:26 EDT 2006
    x86_64 x86_64 x86_64 GNU/Linux

    Singe Pentium Fedora4
    uname info unavailable right now

    Fails on:
    Singe Xeon SuSE 10.1
    Linux xxxx 2.6.16.13-4-smp #1 SMP Wed May 3 04:53:23 UTC 2006 i686
    i686 i386 GNU/Linux

    Single Celeron 400 (Embedded BlueCat)
    Linux 2.6.7 #45 i686 i686 i386 (not copy pasted)

    Single Celeron 400
    SuSE 10.1 - not available


    My solution (others have done the same) was to go back to having the
    gui thread call its own event_generate method with the event string
    passed in through queue and using a polling loop with after methods.

    Would someone please verify that this shouldn't be done for some reason
    such as thread-safety or point out what I'm doing wrong? It seems from
    some of the errors that the event data is getting overwritten. I've
    included the code, if anyone wants to see some of the errors I have
    saved them.

    ---------------------------
    from Tkinter import *
    import threading
    import Queue
    from time import sleep
    import random

    class Thread_0(thread ing.Thread):
    def __init__(self):
    threading.Threa d.__init__(self )

    def run(self):
    count=0
    while True:
    count+=1
    hmi.thread_0_up date(count)
    sleep(random.ra ndom()/100)

    class Thread_1(thread ing.Thread):
    def __init__(self):
    threading.Threa d.__init__(self )

    def run(self):
    count=0
    while True:
    count+=1
    hmi.thread_1_up date(count)
    sleep(random.ra ndom()/100)

    class HMI:
    def __init__(self):
    self.master=Tk( )
    self.master.geo metry('200x200+ 1+1')

    f=Frame(self.ma ster)
    f.pack()

    self.l0=Label(f )
    self.l0.pack()
    self.l1=Label(f )
    self.l1.pack()

    self.q0=Queue.Q ueue()
    self.q1=Queue.Q ueue()

    self.master.bin d("<<Thread_0_L abel_Update>>", self.thread_0_u pdate_e)
    self.master.bin d("<<Thread_1_L abel_Update>>", self.thread_1_u pdate_e)

    def start(self):
    self.master.mai nloop()
    self.master.des troy()

    ############### ############### ###
    def thread_0_update (self,val):
    self.q0.put(val )
    self.master.eve nt_generate('<< Thread_0_Label_ Update>>',when= 'tail')

    def thread_1_update (self,val):
    self.q1.put(val )
    self.master.eve nt_generate('<< Thread_1_Label_ Update>>',when= 'tail')

    def thread_0_update _e(self,e):
    while self.q0.qsize() :
    try:
    val=self.q0.get ()
    self.l0.config( text=str(val))
    except Queue.Empty:
    pass

    def thread_1_update _e(self,e):
    while self.q1.qsize() :
    try:
    val=self.q1.get ()
    self.l1.config( text=str(val))
    except Queue.Empty:
    pass

    ############### ###########
    if __name__=='__ma in__':
    hmi=HMI()
    t0=Thread_0()
    t1=Thread_1()
    t0.start()
    t1.start()
    hmi.start()

    ---------------------------

Working...