spawn batch of worker threads on each mouse click: may overlap
text = ScrolledText()
text.pack()
threadChecker(text) # start thread loop in main thread
text.bind('
lambda event: list(map(onEvent, range(6))) )
text.mainloop() # pop-up window, enter tk event loop
This module’s comments describe its implementation, and its self-test code demon-
strates how this interface is used. Notice how a thread’s behavior is split into main
action, exit actions, and optional progress action—the main action runs in the new
thread, but the others are queued to be dispatched in the main thread. That is, to use
this module, you will essentially break a modal operation into thread and post-thread
steps, with an optional progress call. Generally, only the thread step should be long
running.
When Example 10-20 is run standalone, on each button click in a ScrolledTest, it starts
up six threads, all running the threadaction function. As this threaded function runs,
calls to the passed-in progress function place a callback on the queue, which invokes
threadprogress in the main thread. When the threaded function exits, the interface
layer will place a callback on the queue that will invoke either threadexit or thread
fail in the main thread, depending upon whether the threaded function raised an ex-
ception. Because all the callbacks placed on the queue are pulled off and run in the
main thread’s timer loop, this guarantees that GUI updates occur in the main thread
only and won’t overlap in parallel.
Figure 10-12 shows part of the output generated after clicking the example’s window.
Its exit, failure, and progress messages are produced by callbacks added to the queue
by spawned threads and invoked from the timer loop running in the main thread.
Study this code for more details and try to trace through the self-test code. This is a bit
complex, and you may have to make more than one pass over this code to make sense
of its juggling act. Once you get the hang of this paradigm, though, it provides a general
scheme for handling heterogeneous overlapping threads in a uniform way. PyMailGUI,
for example, will do very much the same as onEvent in the self-test code here, whenever
it needs to start a mail transfer.
Passing bound method callbacks on queues
Technically, to make this even more flexible, PyMailGUI in Chapter 14 will queue
bound methods with this module—callable objects that, as mentioned, pair a method
function with an instance that gives access to state information and other methods. In
this mode, the thread manager module’s client code takes a form that looks more like
Example 10-21: a revision of the prior example’s self-test using classes and methods.
644 | Chapter 10: GUI Coding Techniques