During Thom’s “Threads” session, we were reminded again, and in no uncertain terms, that App.DoEvents is evil and should never be used where there is already an event loop. The question was raised as to why it is not removed and the answer was that it would break existing code.
I’d like to make the case that the reasoning is faulty, and it should be removed now.
(Again, this is only for projects where it should not be used.)
If App.DoEvents is being used, the code, by definition, is already “broken”. By removing the ability to use it, you force users to rewrite their code properly and thus “un-break” it. In short, you are doing users a favor, even if they don’t think so.
I do not think it should be removed completely, but I do think it coud be deprecated in favour of something like app.LetSystemDoStuff which could do what ever is appropriate for the app being built - so for a console app it would do DoEvents, and for web apps, desktop apps, IOS apps etc it would do whatever is deemed apropriate, wether that is sleeping for a few milliseconds, or yielding control in somne other way.
I’m sure quite a lot of us have used it over the years here and there without any issues. I quickly search my biggest project (desktop app), and there are four occurrences (dating back to 2009 when I started it).
I don’t want to be forced to re-work these parts of my project within the next few weeks. But I know that I will have to do it in the next 12 months or so. Deprecation would be perfect for that.
Curious: What is the alternative when there is a long and complex loop based computation going on?
Without app.doevents now and then, Windows in particular is very keen to tell the user that your app which is working very hard is in fact dead and needs to be nuked.
DoEvents is already disabled in Threads. It simply yields under the hood. The problem is when it is used in the main thread. Any code that uses DoEvents in the main thread should be moved to thread object. That will require some adjustment of the app, because now the UI will be responsive and you have to prevent the user from clicking something that he shouldn’t.
Hear this: because of the way Xojo implements threads, moving code to a thread is easy. Very easy. Brain-dead easy. There is no excuse for not doing it. Besides, as Kem already pointed out, your app was “broken” already. You can’t break it much worse.
I still don’t get this “doevents is evil”… (GOTO is evil, that I understand)…
So could someone educate me here (not as to alternatives, but as to why it is unto itself “evil”)
My understanding is that during the course of execution, messages are sent to a stack to be sequenctally executed at a point in time when there is “idle time” (the definition of which I will leave for another day)… When these slices of time become available, if there is a message waiting on the stack, that message triggers an event (Paint for example)… The message stack here being a FIFO (first in, first out).
And all “DoEvents” does is say. “Hey Application!, Hold up for a millisecond or two, while I force the message queue to fire all events currently on the stack”… If that is a true description, how is that evil? Of course it needs to be used with discretion, otherwise you are interuppting you own app more often than necessary. But I have seen situations where the careful use of DoEvents keeps the GUI active, without the need to create a thread. And while threads are easy to create, the logical seperation of code between main and thread is not always so straight forward.
Having debugged and repaired a few projects where DoEvents was used inappropriately to overcome bad design mistakes, I’d say that the “DoEvents is evil” comes more from the results of how it ends up getting abused than from the bottom up reasoning of why it’s to be avoided. So, I’d simply say it’s evil because it causes bad problems.
While it is possible to produce code that doesn’t malfunction, that is not within your control. It’s just as likely to create a stack overflow as to work flawlessly. The fact that there are situations where your app doesn’t crash doesn’t mean that it is safe to use. This unpredictability is what makes it “evil”. It is similar to the “updating the UI from a thread” issue.
It causes the main event loop to be reentered and reentrancy causes the problems.
You can literally have an the main event loop cause an event to get entered which then calls do events which could cause the main event loop to run which can cause an event to get entered which then calls do events . and so on.
Note that the first event is not finished before subsequent ones could run.
I have helped people on the forums who have been bit by this. The one that immediately comes to mind caused a cascade of socket DataAvailable events that scrambled the processing of that data. He got wildly unpredictable results and couldn’t track it down.
App.DoEvents should throw a RussianRouletteException in all but a non-event-driven Console app. The arguments for using DoEvents in a GUI app boil down to “There may be a landmine buried somewhere on this path through the field, but we have walked this path a hundred times without harm, so it must be safe.”
I’m sure having a compile time warning about Doevents in GUI apps and in any place other than the Run Event of a console/service app is a good place to start.
Perhaps looking at why people are using this in the wrong place and providing an alternative solution is a better way to go though. In my early days I thought doevents was a good way to release resources while waiting for something to happen. Adding a mechanism to sleep the current process without reentering the event loop seems to be a common requirement.
Yes I know it’s teaching bad coding techniques to newbies, but what is doevents doing?
DoEvents is the meat of the event loop. Imagine the event loop looks like
While True
App.DoEvents
Wend
A stack trace from PushButton1.Action could be represented as
Window1.PushButton1_Action
App.DoEvents
main
(Both sets of code are fake, just trying to paint you a picture)
So calling App.DoEvents from ANY code started from an event - which is all of it - is the definition of recursion. It will produce strange stack traces, unpredictable behavior, and incorrect exception handling.
Why do people use DoEvents? It can be described as “poor man’s threading.” Whenever I see it used, it is done so to avoid refactoring code to use threads. It is done for convenience. Which, in my opinion, is synonymous with laziness.
I’ve been there, used App.DoEvents even knowing all this. Every single time, it has come back to bite me. You may not even realize it is the culprit behind some other behavior, that’s what makes it evil. It is a traitor. It appears to work in your favor, but it is secretly working against you.
It never should have been possible to use from a Desktop or Web app. But the flag was not set when it was introduced, and Web apps need it, but not for any code you can control. Before you ask, Web apps use it in exactly the way it was intended to be used.
It is a console app function designed to allow you to build an event loop, since console apps normally do not have one. There is no other purpose.