"fooooo" <ph*****@yahoo.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
This is a network app, written in wxPython and the socket module. This
is what I want to happen:
I'm not sure if this will help you, but it solved what was, for me, a
more general problem: not (normally) being able to issue wxPython calls
outside the GUI thread.
I came up with a general-purpose thread-switcher, which, given a
callable, would on invocation:
queue itself up on the GUI event queue
call its callable in the GUI thread (allowing arbitrary wxPython
calls)
pass its result back to the calling thread (or re-raise any exception
there).
Instead of having a dedicated queue, it uses one already in place.
Because all calls using it are serialized, it had the beneficial
side-effect (for me, anyway)of avoiding certain concurrency issues.
(The calls to my locks module, CheckPause() and CheckCancel(), were
there so the user could suspend, resume, and cancel worker threads at
will, which the Python threading module does not naturally support(my
locks module held some state that could be set via the GUI.) If you have
no need of that, delete those lines and everything should still work
(they were a late addition).
import wx, threading, types
import locks # my code, see remark above
#-------------------------------------
# decorator used to call a method (or other callable)
# from the wxPython main thread (with appropriate switching)
#--------------------------------------
class wxThreadSwitch(object):
def __init__(self, callable):
object.__init__(self)
self.callable = callable
def __get__(self, inst, owner=None):
c = self.callable
# if c is a descriptor then wrap it around
# the instance as would have happened normally
if not isinstance(c, types.InstanceType):
try:
get = c.__get__
args = [inst]
if owner is not None:
args.append(owner)
return wxThreadSwitch(get(*args))
except AttributeError:
pass
# if we get here, then not a descriptor,
# so return self unchanged
return self
def __call__(self, *args, **kwargs):
if wx.Thread_IsMain():
return self.callable(*args, **kwargs)
locks.CheckPause()
c = self.__wxThreadCall(self.callable)
wx.CallAfter(c, *args, **kwargs)
return c.Result()
class __wxThreadCall(object):
def __init__(self, callable):
assert not wx.Thread_IsMain()
object.__init__(self)
self.callable = callable
self.result = None
self.exc_info = None
self.event = threading.Event()
def __call__(self, *args, **kwargs):
try:
try:
assert wx.Thread_IsMain()
assert not self.event.isSet()
locks.CheckCancel()
self.result = self.callable(*args, **kwargs)
except:
self.exc_info = sys.exc_info()
finally:
self.event.set()
def Result(self):
self.event.wait()
if self.exc_info:
type, value, traceback = self.exc_info
raise type, value, traceback
return self.result
A usage example would be to decorate a function or method with it:
class Something:
@wxThreadSwitch
def someGUICallOrOther():
....
Here the method call would run via the wxThreadSwitch decorator which
would do any necessary thread switching.
Hope this helps
John