This is now easier to use, IMO. Feedback welcome.
Oliver
DelayedResult.py (5.68 KB)
···
-----Original Message-----
From: Oliver Schoenborn [mailto:oliver.schoenborn@greenley.ca]
Sent: August 3, 2006 9:57 AM
To: wxPython-users@lists.wxwidgets.org
Subject: [wxPython-users] interest in DelayedResult?I have created a module called DelayedResult.py (still prototype, but
works) that helps use multithread in GUI apps, something many
novice users are not comfortable with. It's basic use case is:- you have a task, triggered by a GUI event, that takes more than
1/10th sec to execute, so you loose GUI response in that time
- starting the task from the event handler actually involves going
through one or more layers with pre-processing at each level; e.g.
handler calls slowTask, which does some setup stuff then itself
calls lowerLevelSlowTask, which starts the thread and
returns immediately
- when the task is done, the result is new data that must be
pushed to the GUI
- once the result is available, each (or at least one) level needs to
do some post-processing before the final result can be sent to GUIDelayedResult makes it really easy to get the final result
back from the thread to the GUI, without having to know
anything about creating new event types or CallAfter etc. It
manages the reverse chain of "callers", makes it a lot easier
to transform a single thread impl to a multi-thread
implementation, and makes it easy to see what is pre- and
post-processing of the slow task. It also limits the amount
of synchronization code needed. You need WxAppTester.py to
run the module test.Example (pseudo code):
# Single threaded case:
handle_download(self, event):
# get file from web server:
fileObj = serverProxy.get_file( theFile ) # blocks/takes long
ask_user_where_to_save() # post-processing
update_tree_view()class ServerProxy:
...
get_file(self, theFile):
... pre-processing, e.g. add complete path to theFile ...
fileObj = NetServices.get_file( theFilePath ) #
blocks/takes long
... post-processing using fileObj ...
return fileObjclass NetServices:
get_file(self, filePath):
... pre-processing ...
... use urlopen etc... blocks here until got it ...
return fileObj# Transform for two threaded case using DelayedResult. Note
how # the structure is the same but post- stuff are now split
into # separate functions:class YourController:
handle_download(self, event):
# get file from web server:
delayedResult = DelayedResult( self.__haveNewResult )
# now returns "immediately" with nothing:
serverProxy.get_file( theFile, delayedResult )__haveNewResult(self, delayedResult):
fileObj = delayedResult.getResult()
ask_user_where_to_save() # post-processing
update_tree_view()class ServerProxy:
...
get_file(self, theFile, delayedResult):
... pre-processing, e.g. add complete path to theFile ...
delayedResult.prepend( self.__haveNewResult )
# now returns "immediately" with nothing:
NetServices.get_file( theFilePath, delayedResult )__haveNewResult(self, delayedResult):
something = delayedResult.getResult()
... post-processing using something ...
return fileObjclass NetServices:
...
get_file(self, filePath, delayedResult):
... pre-processing ...
def threadedFn(delayedResult):
fileObj = urlopen(...) # blocks/takes long
delayedResult.sendResult(fileObj)
thread.start_new(threadedFn, (delayedResult,))Would it make sense to have it in wx.lib?
Oliver