Hi:
While tracking down those pesky recursive Yield problems I realized
that the way we use Yield in Chandler has several problems. So if you
use, or plan to use, Yield in your code you might want to read what
follows:
wx.Yield is deprecated. Use wx.GetApp().Yield() instead.
Calling the Yield method on the application object while in Yield is
a bug, i.e. Yield is not reentrant. The debug version of wxWidgets
throws an assert in this case (that bug is assigned to me). If you
need to call Yield and you're not absolutely sure you're not being
called from Yield, you should pass True to Yield, i.e. wx.GetApp
().Yield(True), which will return instead of recursing in this case.
When you call wx.GetApp().Yield, and the user performs some action,
that action will be processed, which can causes subtle bugs and/or
cause Yield to recurse. For example, all the non-recorded scripts
call wx.Yield so that while the tests are running you can interact
with Chandler. This is a great way to mess up the tests. A safer
approach is to disable user actions during Yield. You can do this by
calling wx.SafeYield(None, True) -- the None argument blocks user
actions from all windows; the True argument avoids recursing as in
the wx.GetApp().Yield(True) case above.
There appear to be a few situations where you'd think calling calling
wx.SafeYield(None, True) would work, but it doesn't. These situations
seem to happen when emulating typing or clicking in the old script
framework.
So, to summarize, most of the time we should probably be using
wx.SafeYield(None, True), followed by wx.GetApp().Yield(True) when
you want to let users issue commands during the Yield; wx.GetApp
().Yield() should almost never be called and absolutely never call
wx.Yield().
Here's what the wx documentation has to say about Yield:
wxApp::Yield
bool Yield(bool onlyIfNeeded = false)
Yields control to pending messages in the windowing system. This can
be useful, for example, when a time-consuming process writes to a
text window. Without an occasional yield, the text window will not be
updated properly, and on systems with cooperative multitasking, such
as Windows 3.1 other processes will not respond.
Caution should be exercised, however, since yielding may allow the
user to perform actions which are not compatible with the current
task. Disabling menu items or whole menus during processing can avoid
unwanted reentrance of code: see ::wxSafeYield for a better function.
Note that Yield() will not flush the message logs. This is
intentional as calling Yield() is usually done to quickly update the
screen and popping up a message box dialog may be undesirable. If you
do wish to flush the log messages immediately (otherwise it will be
done during the next idle loop iteration), call wxLog::FlushActive.
Calling Yield() recursively is normally an error and an assert
failure is raised in debug build if such situation is detected.
However if the onlyIfNeeded parameter is true, the method will just
silently return false instead._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Open Source Applications Foundation "chandler-dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/chandler-dev