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

Reply via email to