[wxPython-users] Latest DelayedResult implementation
Oliver Schoenborn
oliver.schoenborn at greenley.ca
Fri Sep 1 13:04:31 PDT 2006
> -----Original Message-----
> From: Josiah Carlson [mailto:jcarlson at uci.edu]
> Sent: September 1, 2006 12:02 PM
> ...
> The three simplest cases I provided in the
> 10-minutes-to-write AltDelayedResult.py would likely be
> sufficient for the vast majority of users, and are also
> *very* simple to understand.
I would say that AltDelayedResult.py has little advantage over just
using wx.CallAfter:
thread.start_new_thread( workerFn, (goo,) )
def workerFn(cb):
result = something
wx.CallAfter(cb, result)
The only advantage of your example module is that it starts the thread
for the user, something I have not wanted to do so far. However it may
be a good idea for the novice.
> The trick is providing the right amount of functionality
> without confusing users.
I agree completely on that one.
> I also don't believe that having variables that define
> channels is generally useful.
In the very first implementation (which I believe I posted), all
functionality was in one class: DelayedResult.DelayedResult; the concept
of channel was not explicit so you never created it. The problem with
that is that it didn't make it clear what to do in what order. The
separation of the concepts of channel, sender, and result (and I guess
maybe I could add thread) helps with this since each one has a small
number of operations available.
> > > With the API I provided, say I have a function foo that I want to
> > > call with arguments a,b,c and get results back via wx.CallAfter on
> > > goo, I would do:
> > > ReturnWithCallAfter(goo, foo, a, b, c)
> >
> > DelayedResult leaves it up to you (intentionally) to create/manage
> > your thread function. So I end up with exactly the same call as you,
> >
> > with e.g. (not tested)
> >
> > def ReturnWithCallAfter(listener, fn, *args):
> > def threadedFn(fn, sender, *args):
> > sender.sendThreadResult(fn(*args))
> > channel = byCall(listener, *args)
> > thread.start_new_thread(threadedFn, (fn, channel.getSender()))
>
> I claim that the 3 base mechanisms I provided earlier are
> sufficient for the majority of uses. If your module requires
> that much code to get what I consider to be the base
> mechanisms, then your module lacks the easiest to understand
> functionality, while including functionality that needs to be
> heavily documented and exemplified in order to be understood.
Your module hides a _ReturnWithPostEvent which starts a thread, whereas
DelayedResult chose to leave it up to the user to do that, so naturally
an extra function is needed. It's pretty obvious that my "extra code" is
your _ReturnWithPostEvent.
> Remember: some people have difficulty getting the value of a
> text control. You think they are going to get channels?
> Thread creation?
People learn step by step. One doesn't (voluntarily :) tackle threads
until confortable with the more basic stuff. As soon as the concept of
thread enters, all sorts of things must be considered: e.g. has the
document changed while your result was being computed, such that the
result is no longer relevant? is the result still needed by the time it
is available (user may have changed their mind)? etc.
The use cases that DelayedResult caters to are not trivial, so I
wouldn't expect a novice to be able to figure it out without some
experimentation.
> channel.getSender() (which is actually closer in
> functionality to channel.getReciever(), as they will be
> recieving the output of the call...)
Definitely not. The receiver is the "goo" in your original example, ie
the top-level listener, one end of the channel. The sender is the other
end: it sends the result out to cross from one thread to the other
(using the channel and wx.CallAfter etc).
So to summarize: you find DelayedResult more complex than necessary
(complexity is not useful since if more than the simple case is needed
then what DelayedResult provides will be insufficient), and that
DelayedResult is more complex than most people would be able to handle.
Those are all subjective statements. For me, the ability of
DelayedResult to support encapsulation (which is not unrelated to
chaining) is a requirement, not just a "nice to have" so the simpler
approach you provide is not useful. And I figure, if I needed
DelayedResult, perhaps someone else will.
The things I get out of this discussion are good (IMO): 1) I should add
a helper that makes it unnecessary to create thread explicitely (while
allowing user to choose which thread module to use, IF default not
adequate); 2) I should explain the basic concepts better; 3) I should
move the testing to a separate file so that module can be used in py 2.3
too; 4) Any other suggestions welcome.
Oliver
More information about the wxpython-users
mailing list