Making the case to remove App.DoEvents

Its intent was strictly for console based apps without an event loop
GUI apps should never have had it but there was a slight error way back when & it’s been there ever since with lots of interesting bug reports & such in between :slight_smile:

We fed them and watered them with https://www.myxojo.com

Why ?

Because you have used it a lot ?

Didn’t mean to start a war here. I meant to corner Norman after Thom’s session to make the case and just never had the chance.

Removing update UI from thread give a lot f work to some of us. Removing App.DoEvents will do the same.

I use App.DoEvents but I disable all the UI except a stop button. Then the user can move the window and stop the process. And, just a remark, some version of RealStudio ago, the progresswhell wasn’t animated without DoEvent.

I came to RealBasic long time ago for its easy of use. Remove this easy of use and …

For those of you who are professionasl developpers, ask Xojo to add an evil on the icon of the built application which use App.DoEvent ! So users will make the difference. Sometimes, when I read this forum, I have the sensation to be kicked out !

Thomas, you’ve already done 99% of the work necessary to move your code to a thread it seems. You might be very surprised just how easy it would be for you to dump DoEvents.

It turns out there was already a Feedback case for this, even if it was marked resolved. I’ve added my case to it.

<https://xojo.com/issue/2518>

Read Ramblings on Realbasic by Aaron Ballman
Page 19 “Why is App.DoEvents Evil?”
While it was marginally improved years ago it still has issues and as Aaron wrote
[i]former REAL Software engineer, Mars Saxman, explained it in the most eloquent way:

DoEvents is not just a yield function. It does yield to other threads, but it also runs the event loop. If you call it from threads other than the main thread, you will end up splitting your main event loop across multiple threads. If you are unlucky, this will not cause any problems right away, and you will think your program works. Then one of your users will manage to get the timing just right and your app will wind itself up with one DoEvents call inside another until your stack overflows.
[/i]

Evil because your app is OK until its not and then you have no idea why or how to fix it.

Just some observations…

  1. DoEvents within console apps is fine and a necessary feature.

  2. In non-console apps…

If I understand Kem’s comment…

The substitute for App.DoEvents already exists in Threads and Timers, and there is already App.YieldToNextThread.

and Tim’s

DoEvents is already disabled in Threads. It simply yields under the hood

then DoEvent within a thread or timer is now safe, as the correct thing is now done under the covers.

…which leaves us with DoEvents in the main thread of a GUI app…

In Norman’s quote from Mars Saxman…

…If you call it from threads other than the main thread…

Implies DoEvents is OK from the main thread

and the documentation from the language ref, invoked from the IDE, includes a warning regarding instability…

Using DoEvents in a GUI application will likely cause instability

which is not quite as strong as some of the wording on this forum,

and the phrase…

Since DoEvents keeps the user interface responsive while the loop is running

which implies it has its uses sometimes.

No alternatives are documented there.

Documentation changes to, at least, increase the severity of the warning and probably to show the alternatives, might be a good idea.

Austin, we have a problem… :wink:
I understood it exactly like Chris.

IF DoEvents is unsafe on the main thread, then I’m all for it to remove it. Anything that causes our apps to crash needs to be fixed/removed because it gives a bad impression to Xojo and our apps.
Otherwise let in in, because it prevents code spaghettiration/complexity.

An example where I use DoEvents is App.CancelClose:
Do Until (extLogging.Timer_Log.Mode = Timer.ModeOff)
DoEvents…
Loop

That “Timer_Log” exists only because of “don’t update the GUI from a thread” because my logging-class may update the GUI…so if a thread wants to log something to the GUI, it is catched and directed to a Timer…

Now it happend that log entries are missing or things go Nil (don’t remember exactly), that’s why I check & wait on App-Quit for the Timer to complete. Without DoEvents the app just hangs because the Timer never get’s a chance to do anything…
I could solve this by returning false from App.CancelClose + another Timer which repeatedly calls Quit + some Statics in App.CancelClose to check which code portions already have been executed.
But, it doesn’t make my code more understandable…

Or you could move the Timer.Action code to its own method and call it directly instead of waiting for the Timer period. (I guess, based on your description.)

Do Until (extLogging.Timer_Log.Mode = Timer.ModeOff)
  YieldToNextThread()
  DoTimerLogAction()
Loop

@Chris Carter Some of those quotes come from ages ago before the behavior was tweaked.

I’m honestly not sure why this is up for debate. I am an ex-Xojo developer. Norman is a current Xojo developer. We are telling you in no uncertain terms that using it this way is against the rules. The problem is that the rule is currently not enforced. This isn’t like GOTO where it is simply not recommended for code design reasons, but still works fine if you want to use it. This should cause a compile error at best, or an exception at worst.

Since the language allows it, what the people who design the language say doesn’t matter, right? Same thing with threads accessing the UI.

Let me recap:

  1. DoEvents is not the same as the VB equivalent.
  2. DoEvents was designed only for console apps.
  3. Its behavior changed at one point to be an alias for YieldToNextThread when called outside the main thread.
  4. In most cases where you want DoEvents, you actually want YieldToNextThread.
  5. Odds are you will be forced to stop using it. Either by deprecation and removal, or by it not existing in the new Xojo Framework. Prepare now.

I’m not sorry I kicked this hornet’s nest, because these are talks we need to have. The fact that we’re still arguing about it proves just how much misinformation there is on the subject.

Oddly, the only misinformation seems to be, “It works for me”. It’s not as though anyone has any special technique that allows its use in GUI applications.

Kem: That’s a nice idea, less clutter, thanks!
As the timer-logging-stuff is all made with AddHandler I have the Timer_Action separated already.
The only drawback is I have to make Timer_Action Protected instead of Private. So from the encapsulate-as-much-as-possible standpoint it’s a (very little) step back.

I think the YieldToNextThread() isn’t really necessary since App.CancelClose is anyways always executed on the main thread, right?

Everything I quoted comes from either this thread or current Xojo reference.

I wasn’t trying to debate, or to annoy anybody, just to illustrate that I think a documentation update might help to cure some of the confusion.

I have already mentioned earlier in the thread that I am in favour of deprecation of the nasty occurances of DoEvents.

Yes, but those quotes are not necessarily up to date. For example, you quoted Norman Palardy quoting Mars Saxman. Mars’ comment is from roughly 6 years ago. Behavior has changed since then. He left the company before I even started.

Yes, a documentation update might help. But it probably won’t. People really want to do it this way.

Mars quote is slightly before the behavior was changed but Aaron made a blog post about it AFTER the change and still said


So here’s the definitive list of when it’s safe to use DoEvents: From the main thread of a console application. That’s the whole list.
Note from Aaron: The DoEvents API was modified in later versions of REALbasic to behave better, especially for GUI applications. However, I am still not ?comfortable advocating its use. It can solve some problems while creating problems elsewhere. I’d still avoid using it unless you have run out of other options.

Seriously - and he’s the guy that made the behavior change.
But still its been many years since we started saying “don’t do this” (like 8 or 9) and people still do because “it seems to work for me”

We still get bug reports that we can trace back to using doevents (reentrancy & other related “bugs”) that we simply ship back & say “don’t do that as that IS what causes the problem”

I suggest locking this thread now. Its clear the decision has been made by Xojo Inc.

[quote=75392:@Chris Carter]In Norman’s quote from Mars Saxman…

…If you call it from threads other than the main thread…

Implies DoEvents is OK from the main thread[/quote]
But it isn’t. The quote from Mars was addressing the worst case: using DoEvents in a thread (where there was never any reason to do, since you can Yield instead). That was a real killer. Enough so that Xojo made what amounts to a hack and changed the behavior of DoEvents when called in a non-main thread.

But that doesn’t mean that it is in any way safe to use in the main thread. It is not. I’ve seen the carnage. And again, the real problem is that it does not manifest itself in a predictable manner. It’s a timing issue, so code that has worked flawlessly for months can suddenly malfunction. And then start working again, or not.

Car manufacturers and alcoholic beverage producers both say not to drink and drive, yet every day many people do… Those that appreciate what you are telling them will make the changes required, the others won’t - same goes for this topic…