• Quite (unregistered)

    That's a bit like not understanding how (mechanical) transmission works, and so you build the engine directly onto one of the wheels.

  • bvs23bkv33 (unregistered) in reply to Quite

    I don't get a metaphor: it is ok to build an engine directly onto the wheel, unless you want to build a steam/gas car, electric cars and trolleybuses will go too

  • Quite (unregistered) in reply to bvs23bkv33

    Designing a motor that is physically attached to a wheel is perfectly okay when the particular circumstances warrant it. But making that design decision as a result of ignorance of a basic engineering technique and thereby using that design when the circumstances do not warrant it, that is a WTF.

  • foxyshadis (unregistered)

    Non-VB people might not realize the true WTF: DoEvents isn't just a yield with a short timeout, it instantly returns, making it a CPU busy loop -- great way to exercise a new core's Turbo Boost. The only good thing I can say about the function is that at least it's easy to replace with Sleep().

  • Derp (unregistered)


  • Stine (unregistered) in reply to bvs23bkv33

    It also makes sense if you're building an embedded car with no file system.

  • Ron Fox (google)

    I don't get how the loop ever exits since Now is updated outside of the loop.

  • RichP (unregistered)

    My programming PTSD kicked in as soon as you said "process window messages". I woke up lying on the floor screaming "DoEvents! DoEvents, move you &*%# progress bar... cancel cancel... CANCEL!!" shudder...

  • Trust Me I'm Not A Robot (unregistered)

    This code was clearly written by someone who came from Visual Basic 6.0 and is not familiar with how .NET works.

  • djingis1 (unregistered)

    DateTime in .NET is immutable. Now.AddSeconds(1) returns a new instance with an added second. It does not change the original instance.

  • jmm (unregistered) in reply to Trust Me I'm Not A Robot

    There's a good chance it IS VB6 code, carried over from a legacy application into the brave new world of VB.Net

  • GW (unregistered)

    TRWTF is being able to add the comment above the function(thus realising it's an abomination) but being unwilling/unable to just refactor it to be less crap. Even just making it thread.sleep for 100ms each time around the loop would be better, and the whole OneSec thing is just stupid & completely pointless. I would not have been able to see this and not do something to improve it.

  • Bruce W (unregistered) in reply to RichP

    Yes, serious PTSD with DoEvents. When all else failed, add more DoEvents....

  • Wounded VB Warrior (unregistered)

    TRWTF is using "DoEvents" unironically

  • TimothyB (unregistered) in reply to Ron Fox

    Assuming that Now means System.DateTime.Now, each use of it gets the current "now" (in local time, so it can go backwards an hour once a year...)

  • Jeremy Hannon (google)

    Definitely VB6 (or prior) carryover. DoEvents itself is a carry over from Windows 3.1, where you had to call it in order to allow the system to process other threads. This was "cooperative multi-tasking". Windows 95 introduced the Preemptive Multi-Tasking and programs built for Win32 did not need this. Granted I did not do any programming targeting Windows 3.1, but I did read the books.

  • Mike C (unregistered)

    I'd bet that code is running on the UI thread (as a result of a button click or something) and therefore the user doesn't want a Sleep().

    Still, that whole issue goes away with Async/Await and tasks.

  • Scott Christian Simmons (google)

    That CodingHorror blog entry, and the MSDN chat it quotes, date to 2004, and reference .NET 1.1. Inadequate threading support barely scratches the surface of the horrors hiding within that platform. Using ugly VB6 code that worked rather than technically correct VB.NET code that didn't was a common survival practice in those dark days.

    (If you want to find out if someone did any web design in ASP.NET 1.0 or 1.1, just walk up to them and ask, "Hey, do you remember any issues with ASP.NET 1.1 garbage collection?", and see if they scream and curl up into a fetal position.)

  • John Wiltshire (github)

    If in doubt, add more DoEvents. VB programming rule #1.

  • Former Classic VB Programmer (unregistered)

    DoEvents was necessary. In my limited knowledge, VB didn't do multithreading.

    And yes, I remember the early VB.Net and ASP.Net implementations. It's a miracle Microsoft survived that.

  • Bill C. (unregistered)


    I do like to add seconds.

  • Confused (unregistered)

    Am I missing something here? What's with the 1440?

  • Doug (unregistered) in reply to Confused

    What's with the 1440?

    You mean the one in "Const OneSec As Double = 1.0# / (1440.0# * 60.0#)"?

    Well, imagine you want to define OneSec, and "1.0" means "one whole day". To make your intent clear you'd say "OneSec = 1.0 / (24 * 60 * 60)", to make it obvious that you're dividing by 24 hours in a day, then by 60 minutes in an hour, then by 60 seconds in a day. Or just "OneSec = 1.0 / 86400", because most programmers will recognize "86400" as "number of seconds in a day". Now imagine that instead, you want to make your intent unclear. So you use 1440, which is "number of minutes in a day", and then divide that by the number of seconds in a minute.

  • Norman Diamond (unregistered)

    To avoid leaping WTFs, the program has to look up the date and decide whether to divide by 86401 or just 86400.

  • Yazeran (unregistered) in reply to Doug

    Wow. Bonus points for obfuscation! I'm old enough to immediately think 'floppy drive' when seeing a number like 1440 or 1.44 (I'm nut sure if this is a good thing though grin)


    Plan: To go to Mars one day with a hammer

  • (nodebb) in reply to Yazeran

    It's worse than that, actually. A 1.44 MB floppy disk wasn't actually 1.44 megabytes (even if you ignore all the overhead stuff).

    No, it was 2880 sectors of 512 bytes, that is 1440 KiB. 1.44 thousand KiB, or 1.44 kilokibibytes. (Decimal megabytes are kilokilobytes. Binary megabytes, mebibytes, are kibikibibytes. The 1.44MB floppy was 1.44KKiB, and it was NEITHER 1.44 KKB NOR 1.44KiKiB.)

  • isthisunique (unregistered)

    It takes days as a float? Does modifying Now like that actually change the clock on the PC?

    24 * 60 * 60

    Oh but lets precompute 24*60 because everyone knows off the top of their head how many minutes are in a day.

  • Chris (unregistered)

    The need of using DoEvents reveals that even modern Windows versions do cooperative multi-taskting. Hence Microsoft still uses good old source code of Windows 3.11. That's Microsoft's definition of multi-tasking: it needs to be cooperative. Question: "Protected Mode?", Answer: "Never heard of"

  • CSharpProgrammer (unregistered)

    @foxyshadis DoEvent does not return instantly. DoEvent pumps the message pump. This is very ugly code, but the code ISN'T for threading. It is for asynchronous programming flow using a single thread, which is actually a very valuable thing in a UI program.

    The OP is wrong. Threading should NEVER be used to do this. Instead, (assuming .net 2.0) the correct way to implement this is the schedule the task on the message pump using a System.Windows.Forms.Timer. Assuming .net 4.5 the correct way is to use "await Task.Delay".

  • (nodebb)

    In the Is DoEvents() Evil article, there was one statement that is worth repeating: "It's much better to render part of the form first so the user gets immediate visual feedback, beyond an hourglass cursor, that stuff is happening."

    I click on an icon or a link...and nothing happens. Not even an hour-glass cursor. (Music begins: "This is Final Jeopardy; did it work or just ignore ye...") Finally after 3-5 seconds, the window changes or the app splash screen shows up. There's nothing that makes my day like having an app I don't know if it ignored me, is on vacation, or just taking its sweet time...

    ...I want my instant gratification!

  • Daniel (unregistered)

    Haha! I did very similar things when I was in 6th or 7th grade, writing my first Client/Sever multiplayer game in VB6. My young mind could not get the winsock control on board with sending data to multiple clients in a loop, but the magical DoEvents seemed to fix everything. Oh, the headaches it caused--monsters dying twice from a single blow and all manner of spooky happenings. Events interrupting events in an event driven design. Shameful. This is back in the day when I thought it was a grand idea to write all game logic into a single method--virtually the entire game. Right up until I hit the method size limit.

    Anyhow, to see this sort of abuse so many year later--in a professional environment--written by an adult? I am mortified! You have my condolences!

  • Ugh (unregistered)

    This is perfectly valid code for the time period and context in which it is written: probably late '90's, early '00s VB6 in which case it was IMPOSSIBLE to spawn another thread from the UI thread that you didn't want to sit around locked-up. Is it terrible now? Yes. Was it terrible then? Actually it is quite nice not to lock up the UI while other things are happening.

  • Deanna (unregistered) in reply to Doug

    And on top of that, it uses the "fraction of a day" value, as seconds, 1/86400s , and then trues to wait on it, effectively making that a no-op.

Leave a comment on “Non-Threading”

Log In or post as a guest

Replying to comment #:

« Return to Article