[Chandler-dev] wx.Yield

D John Anderson john at osafoundation.org
Mon Jun 11 19:54:55 PDT 2007


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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osafoundation.org/pipermail/chandler-dev/attachments/20070611/3e653146/attachment.htm


More information about the chandler-dev mailing list