A threaded program should always arrange for a single thread to deal with any given object or subsystem that is external to the program (such as a file, a database, a GUI, or a network connection). Having multiple threads that deal with the same external object can often cause unpredictable problems.
Whenever your threaded program must deal with some external object, devote a thread to such dealings using a
Queue object from which the external-interfacing thread gets work requests that other threads post. The external-interfacing thread can return results by putting them on one or more other
Queue objects. The following example shows how to package this architecture into a general, reusable class, assuming that each unit of work on the external subsystem can be represented by a callable object:
import threading, Queue class ExternalInterfacing(Threading.Thread): def _ _init_ _(self, externalCallable, **kwds): Threading.Thread._ _init_ _(self, **kwds) self.setDaemon(1) self.externalCallable = externalCallable self.workRequestQueue = Queue.Queue( ) self.resultQueue = Queue.Queue( ) self.start( ) def request(self, *args, **kwds): "called by other threads as externalCallable would be" self.workRequestQueue.put((args,kwds)) return self.resultQueue.get( ) def run(self): while 1: args, kwds = self.workRequestQueue.get( ) self.resultQueue.put(self.externalCallable(*args, **kwds))
ei is instantiated, all other threads may call ...