[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

The main difference to notice here, though, is that we call the object pulled off the
queue, and the producer threads have been generalized to place a success or failure
callback on the queue in response to exits and exceptions. Moreover, the actions that
run in producer threads receive a progress status function which, when called, simply
adds a progress indicator callback to the queue to be dispatched by the main thread.
We can use this, for example, to show progress in the GUI during network downloads.


Example 10-20. PP4E\Gui\Tools\threadtools.py


"""
#################################################################################
System-wide thread interface utilities for GUIs.


Implements a single thread callback queue and checker timer loop shared by
all the windows in a program; worker threads queue their exit and progress
actions to be run in the main thread; this doesn't block the GUI - it just
spawns operations and manages and dispatches exits and progress; worker
threads can overlap freely with the main thread, and with other workers.


Using a queue of callback functions and arguments is more useful than a
simple data queue if there can be many kinds of threads running at the
same time - each kind may have different implied exit actions.


Because GUI API is not completely thread-safe, instead of calling GUI
update callbacks directly after thread main action, place them on a shared
queue, to be run from a timer loop in the main thread, not a child thread;
this also makes GUI update points less random and unpredictable; requires
threads to be split into main action, exit actions, and progress action.


Assumes threaded action raises an exception on failure, and has a 'progress'
callback argument if it supports progress updates; also assumes callbacks
are either short-lived or update as they run, and that queue will contain
callback functions (or other callables) for use in a GUI app - requires a
widget in order to schedule and catch 'after' event loop callbacks; to use
this model in non-GUI contexts, could use simple thread timer instead.
#################################################################################
"""


run even if no threads # in standard lib now


try: # raise ImportError to
import _thread as thread # run with GUI blocking
except ImportError: # if threads not available
import _dummy_thread as thread # same interface, no threads


shared cross-process queue


named in shared global scope, lives in shared object memory


import queue, sys
threadQueue = queue.Queue(maxsize=0) # infinite size


#################################################################################


IN MAIN THREAD - periodically check thread completions queue; run implied GUI


actions on queue in this main GUI thread; one consumer (GUI), and multiple


producers (load, del, send); a simple list may suffice too: list.append and


GUIs, Threads, and Queues | 641
Free download pdf