Am 18.07.13 06:38, schrieb fronag...@gmail.com:
On Thursday, July 18, 2013 9:07:24 AM UTC+8, Dave Angel wrote:
Nope - don't use that.  Instead, post an event on the queue, and return
to the mainloop() from whence we came.
          def test_thread(self):
             if self.loader_thread.isAlive():
                 self.root_window.after(100, self.test_thread)
                 return


I see, though it should be noted that your method doesn't actually
block the rest of the even handler code from running, had to fiddle
with it a bit to get that to work. May I ask what exactly is the
rationale behind implementing it like this, though?


Exactly this is the goal of it. Event handlers are supposed to run in as short time as possible, and should never block. The reason is that you want the events to be processed in the order they come in, such that he user can still move the window, resize it, iconify/maximize etc.

That said, the code still looks odd to me. I have used the Tk with multithreading in the past, but directly from Tcl, and not from Python. The basic idea is to have the background thread (which does the work) signal the main thread about its status, i.e. in the worker thread:

for i in range(50):
  some_odd_computation()
  signal('progress', i)

signal('finished')

and in the main thread you bind() to the events fired from the worker thread. That way you don't run any periodic polling.

I fear that Tkinter has a shortcoming which does not allow this pattern to be implemented. The tricky thing is to implement this signal() function, which must post an event to another thread. From the C level, there is Tcl_ThreadQueueEvent() which does this. It arranges for a C function to be run from the event loop of another thread. From Tcl, thread::send does this. To use it from Tkinter, it would be necessary to create a Tcl interpreter in the worker thread *without* loading Tk.

Some day I should dive into the innards of Tkinter to see if this is possible. Then you could implement signal() simply by

def signal(sig, data=''):
tclinterp.eval('thread::send -async $mainthread {event generate . <<%s>> -data {%s}'%sig%data)

and in the main thread bind() to the virtual events.

        Christian


--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to