Why does the version 6 animation control not use a background thread?


Many people have noticed that the animation bar control in version 6 of the common controls no longer uses a background thread to draw the animation. Instead, it acts as if the ACS_TIMER style is always set, even if the caller didn't pass it. Why is that?

The first reason is that the background thread didn't actually help any. In order to draw transparent animations, the painting loop needs to query the animation control's parent to obtain the background color, and that query entails sending a message to the main UI thread. Consequently, the main UI thread must remain responsive to messages in order for the animation to render properly. If the main UI thread stopped responding to messages, the WM_CTLCOLORSTATIC message sent to obtain the background color would hang, and painting would wedge.

Therefore, the UI thread had to remain responsive to messages. And if that's the case, then there's no need for the background thread after all. The UI thread can just run a timer and draw the frames in response to the timer message.

The second reason for getting rid of the background thread is that it actually made things worse. Another thread means more context switches and more memory pressure, since the additional thread needs a stack and other supporting data structures. Admittedly, this is a comparatively weak reason.

The third reason is that using a background thread for painting simply encouraged bad code. Using a background thread for painting meant that the UI thread could stop responding to messages for long periods of time and usually get away with it because the query for the background color comes early in the animation cycle when the main UI thread most likely has not yet gotten into the part of the long-running procedure that stops responding to messages. As a result, the background thread encouraged programs to stop pumping messages on UI threads because "it seems to work fine". The result is programs that fail to maintain a responsive UI, resulting in periodic mysterious hangs in the window manager when another program tries to broadcast a message and gets wedged up behind the unresponsive window. This leads to increased frustration for the end user and a general feeling that "Windows sucks".

By making the suckage obvious, programmers will be more likely to notice that they are doing something bad and do something to address it. Masking the problem with a background animation thread merely allows the problem to persist.

Comments (23)
  1. Interesting. That seems to me like the sort of strategy that people here are always recommending you take (break stuff visibly), as opposed to the sort of strategy you normally do take (bend over backwards to keep stuff working even if they’re doing it wrong). Is there actually a slight shift in policy there, or am I seeing shadows where none exist?

  2. Phylyp says:

    I’m running IE 6 on Windows XP SP2. I notice that when IE is auto-detecting my proxy settings, the Windows logo animation (top-right) freezes at whatever point it is.

    Is this a manifestation of the same case you’ve mentioned here?

  3. Phylyp says:

    Agree with what Scott has pointed out. In the short term, the bending over backwards helps. In the long time though, it merely encourages bad practices.

  4. Gabe says:

    The idea is that you should animate in your message pump thread and do blocking activities in a separate worker thread. The animate control made it seem like you should do blocking activities in your message pump thread and animate in a separate worker thread.

    The old way not only made it easy to implement the wrong behavior, it encouraged it. And the worst part of it is that it could make it seem like your app was working (because the animation is running) while the rest of Windows would lock up (because it was waiting for yoru app to finish blocking).

  5. RichB says:

    Why not just begin drawing the animation on a background thread using a default background colour and simultaneously send an asynchronous request for the true background colour?

    Granted, this may involve 3 threads in total, but hey, we’re in >2Ghz machines nowadays and the context switch overhead is minimal compared to the time it takes to click the mouse.

  6. jab says:

    RichB, We’re in >2Ghz machines certainly but if i have learnt something since i started working in computing is that it is absolutly necesary to save resources wathever it is possible.

  7. comctl says:

    Is the timer less accurate than the thread?

  8. Eli says:

    Isn’t Vista moving things in the opposite direction? I noticed the controls have fancy animations such as the progress bar and seem to run regardless of how unresponsive the host program is.

  9. 8 says:

    I’m on < 1GHz

  10. bob jones says:

    resulting in periodic mysterious hangs in the

    >window manager when another program tries to

    >broadcast a message

    Is this why, when I assign a shortcut key to a shortcut, and I later use that key combo to launch the shortcut, that Windows often just sits there like nothing happened, then the Start button, etc, become unresponsive, and then finally, the app launches and everything I just did to the Start bar happens in fast motion?

    I’ve been wanting to know why this happens forever…

  11. Mike Dunn says:

    I think the difference in this case is that making the bug obvious doesn’t actually break any code. The app still works, it just doesn’t look as good.

  12. Cooney says:

    Granted, this may involve 3 threads in total, but hey, we’re in >2Ghz machines nowadays and the context switch overhead is minimal compared to the time it takes to click the mouse.

    We’re on >2ghz machines for the most part, but we could have fluidly responsive applications on 166MHz machines if our architecture was actually decent. Problem is, this would break lots of applications.

  13. Skywing says:

    Mike Dunn: More likely, the difference is here that old apps don’t use version 6 of the common controls, they get stuck with version 5.  You have to make a manifest to get them to use v6 (i.e. developer does it), in which case there isn’t a binary backwards compatibility issue.

  14. Roland says:

    I noticed that many animations now no longer run smoothly. For example, when emptying the Deleted Items folder in Outlook 2003, the animation performs poorly and sometimes appears to hang. Even in Explorer, the animations sometimes get stuck before they continue.

    The change may have increased the stability of applications, but it impaired the visual quality and smoothness of many animations.

  15. Jorge Coelho says:

    Windows often just sits there like nothing

    >happened, then the Start button, etc, become

    >unresponsive, and then finally, the app launches

    >and everything I just did to the Start bar

    >happens in fast motion?

    That’s Windows hammering your hard disk. Heavy hard disk access still makes Windows multitasking go to hell. :-)

  16. 8 says:

    >Windows often just sits there like nothing

    >happened, then the Start button, etc, become

    >unresponsive, and then finally, the app launches

    >and everything I just did to the Start bar

    >happens in fast motion?

    I’ve seen that a *LOT*! If something /really/ bad happens then after a while when you move the mouse the pc speaker gives a clicking noise while moving.

  17. 8 says:

    PatriotB: Doesn’t that make the balloon look a bit "drunk" in the first place? (lagging behind the parent window a bit as you drag it around)

    But the UI freeze is indeed strange. Does it still happen when you turn off acceleration in the display properties?

  18. PatriotB says:

    >Windows often just sits there like nothing

    >happened, then the Start button, etc, become

    >unresponsive, and then finally, the app launches

    >and everything I just did to the Start bar

    >happens in fast motion?

    That used to happen all the time for me but seems to happen less since SP2 was released.  I believe it’s related to DDE.

    >I’ve seen that a *LOT*! If something /really/

    >bad happens then after a while when you move

    >the mouse the pc speaker gives a clicking

    >noise while moving.

    This type of thing is a totally separate issue from the "explorer freezes" issue.  I’ve seen this happen a few times too–often the system becomes unusable and you have to restart.  I actually encountered this the other day in a program I was writing: I have a tracking balloon tooltip, which would adjust its position whenever the parent window moves (i.e. in response to WM_MOVE).  Well, minimizing the window (and thus moving the window to -32000,-32000) causes the entire UI to soon freeze (sometimes with the aforementioned beeping), leaving no exit but a restart.  I’m using XP SP2, ComCtl32 6; haven’t tested it on other platforms.

  19. Daniel says:

    So previous versions of the Animate *did* use a background thread to do painting? Hmmm, I always thought that worker threads weren’t supposed to touch UI objects? Must admit I do have written a component that does painting in a secondary thread, and it works, but I always assumed it was illegal. Is it perhaps?

  20. Sunil says:

    When programmers do something bad or sucky, the operating system should

    (a) Cover up for it

    (b) Make the suckage as obvious as possible

    There are good arguments in the abstract for both positions, and you’d have to look at each actual case to see which is best for that particular case…

    But I’ve got to believe it’s a mistake to change from (a) to (b) between versions.  Whatever happened to backwards compatibility?

  21. PatriotB says:

    8 – The lag is hardly noticable, at least on my 2 GHz computer, but it is there.  It’s not a big deal for my app, though.

    I didn’t try with turning acceleration off.  As a workaround, I now hide the balloon when the app is minimized (Couldn’t rely on WM_SIZE — that’s too late and it still froze; needed to listen for WM_SYSCOMMAND).  The bug must have something to do with the -32000 thing: right after the main window is minimized (and moved to -32000,-32000), the balloon gets repositioned to the upper left corner (it always has to stay within the desktop, apparently).  The problem may be it trying to draw the "stem" all the way back to -32000…  No idea why it would cause the entire OS to freeze; must be some kind of bug in the kernel portions of GDI/User.

  22. manifest says:

    Can anyone point me to a description how to create a manifest for a simple vc6-app?

Comments are closed.