Problems with Tkinter and threads

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Claus Tondering

    #1

    Problems with Tkinter and threads

    My Tkinter application has to receive events from a TCP connection. I
    have chosen to do this in the following manner:

    The TCP communication takes place in a separate thread. When I receive
    data, I generate an event in the Python application thus:

    app.event_gener ate("<<myevent1 >>")

    In the associated event handler, I do this:

    self.label1.gri d_forget()
    self.label2.gri d()

    This works well if event is generated from a function that is called
    through the after() method of the main frame. But when I send the event
    from my TCP thread, the system hangs in the call to grid_forget.

    Surprisingly, if I replace self.label1.gri d_forget() with
    self.label1.des troy(), things work well.

    What can I do to call grid_forget in this event handler?

    --
    Claus Tondering

  • Paul Rubin

    #2
    Re: Problems with Tkinter and threads

    "Claus Tondering" <claus.tonderin g@gmail.comwrit es:
    The TCP communication takes place in a separate thread. When I receive
    data, I generate an event in the Python application thus:
    >
    app.event_gener ate("<<myevent1 >>")
    I think all bets are off when you do that. Tkinter is simply not
    thread safe and generating events from another thread can trigger race
    conditions and who knows. You need to self-generate events in the
    gui thread with (e.g.) Tk.after, and have those events check for news
    from the TCP thread. You could do that with a semaphore, or more
    pythonically with a Queue.

    Comment

    • Claus Tondering

      #3
      Re: Problems with Tkinter and threads

      Paul Rubin wrote:
      Tkinter is simply not
      thread safe and generating events from another thread can trigger race
      conditions and who knows.
      Does this mean that I cannot even call the main thread's after_idle
      method from another thread?

      --
      Claus Tondering

      Comment

      • Paul Rubin

        #4
        Re: Problems with Tkinter and threads

        "Claus Tondering" <claus.tonderin g@gmail.comwrit es:
        Does this mean that I cannot even call the main thread's after_idle
        method from another thread?
        I'm not certain, I've never tried it that way since there's no way I
        could be confident of its reliability even if it appeared to work.
        Just use after_idle to check for a Queue item and set another
        after_idle event. I generally use about 50 msec (20 hz) which doesn't
        cause any noticable delay for a gui. Call the first after_idle from
        the gui thread when you put up the gui.

        Comment

        • Eric Brunel

          #5
          Re: Problems with Tkinter and threads

          On Mon, 17 Jul 2006 12:58:08 +0200, Claus Tondering
          <claus.tonderin g@gmail.comwrot e:
          My Tkinter application has to receive events from a TCP connection. I
          have chosen to do this in the following manner:
          >
          The TCP communication takes place in a separate thread. When I receive
          data, I generate an event in the Python application thus:
          >
          app.event_gener ate("<<myevent1 >>")
          This is where the problem is: if you do just a event_generate without
          specifying the 'when' option, the binding is fired immediately in the
          current thread. To be sure that an event is created and that the thread
          switch actually happens, do:

          app.event_gener ate("<<myevent1 >>", when='tail')

          and things should work fine.

          HTH
          --
          python -c "print ''.join([chr(154 - ord(c)) for c in
          'U(17zX(%,5.zmz 5(17l8(%,5.Z*(9 3-965$l7+-'])"

          Comment

          • Claus Tondering

            #6
            Re: Problems with Tkinter and threads

            Eric Brunel wrote:
            This is where the problem is: if you do just a event_generate without
            specifying the 'when' option, the binding is fired immediately in the
            current thread. To be sure that an event is created and that the thread
            switch actually happens, do:
            >
            app.event_gener ate("<<myevent1 >>", when='tail')
            >
            and things should work fine.
            Nice!

            Obviously, there are important things that I don't know about Tkinter.
            Unless I'm much mistaken, neither Fredrik Lundh's "An Introduction to
            Tkinter" nor John W. Shipman's "Tkinter reference: a GUI for Python"
            mentions the when='tail' option.

            --
            Claus Tondering

            Comment

            • Eric Brunel

              #7
              Re: Problems with Tkinter and threads

              On Mon, 17 Jul 2006 15:20:46 +0200, Claus Tondering
              <claus.tonderin g@gmail.comwrot e:
              Eric Brunel wrote:
              >This is where the problem is: if you do just a event_generate without
              >specifying the 'when' option, the binding is fired immediately in the
              >current thread. To be sure that an event is created and that the thread
              >switch actually happens, do:
              >>
              >app.event_gene rate("<<myevent 1>>", when='tail')
              >>
              >and things should work fine.
              >
              Nice!
              >
              Obviously, there are important things that I don't know about Tkinter.
              Unless I'm much mistaken, neither Fredrik Lundh's "An Introduction to
              Tkinter" nor John W. Shipman's "Tkinter reference: a GUI for Python"
              mentions the when='tail' option.
              The ultimate documentation is unfortunately still the tcl/tk man pages.
              There is an on-line version here:



              Once you've understood how to convert the tcl syntax to Python/Tkinter,
              it's always the most up-to-date source of information.

              HTH
              --
              python -c "print ''.join([chr(154 - ord(c)) for c in
              'U(17zX(%,5.zmz 5(17l8(%,5.Z*(9 3-965$l7+-'])"

              Comment

              Working...