The dangers of sleeping on a UI thread


If you have a thread that owns a window, you should not be using the Sleep function, because that causes your thread to stop responding to messages for the duration of the sleep. This is true even for sleeps of short duration, such as sleeping for a few seconds and waking up in order to poll the state of something in the system. As we noted earlier, polling is bad for system performance, impairing the system's ability to conserve energy in low power scenarios and suffering from the magnifying effects of Terminal Server. If you're idle, stay idle. If you're busy, do your work and then go idle.

Unfortunately, I occasionally see code like the following:

 // code in italics is wrong
 // bad polling message loop
 bool fQuit = false;
 while (!fQuit) {
  Sleep(2000);
  CheckIfSomethingHappened();
  MSG msg;
  while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
   if (msg.message == WM_QUIT) {
    fQuit = true;
    break;
   }
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }
 ...

Observe that this message loop goes up to two seconds without processing messages. People aren't crazy enough to insert two-second sleeps into threads that are responsible for interacting with the end user, but they often do it for background worker threads which created hidden windows for cross-thread communication purposes. Since the thread has no visible UI, hanging for a few seconds at a time is invisible to the end user.

Until it isn't.

If the system needs to broadcast a message, it will have to wait for this sleeping thread to finally wake up and process the broadcast message. In the meantime, the component that is issuing the broadcast continues to wait. For example, the user may have double-clicked a document that requires DDE to open. The DDE process begins with a broadcast of the WM_DDE_INITIATE message, which stalls behind your window. Your non-responsive hidden window has just created a "Windows seems to hang for a few seconds at random intervals" bug.

Note that many people overlook that calling CoInitialize (possibly indirectly) to initialize a thread for STA creates a hidden window in order to perform marshalling. Consequently, a thread that is running in a single-threaded apartment must pump messages. Failing to do so will result in mysterious system-wide stalls due to the unresponsive window.

But what if you want to sleep for a period of time while processing messages? We looked at this a little while ago.

Comments (48)
  1. PatriotB says:

    On XP, I used to experience, somewhat frequently, Explorer hangs when doing Windows+E to open an Explorer window.  It would sometimes freeze for almost two minutes.  I’d guess it was caused by somebody not responding to a DDE message of some sort.

    Luckily I don’t think I’ve experienced the problem since I installed XP SP2.

  2. Raymond, are there any good methods for identifying the guilty process when a window fails to process its messages in a timely fashion?

  3. ghbyrkit says:

    Raymond, you should correct the code in the example that you cite at the end of your piece.  The parameters are NOT in the right order!  This is true based on empirical evidence of what changes were needed to get it working.  The last comment in that thread shows the correct(ed) parameter order.

  4. Writing a program to detect such windows is left as an exercise. It’s not hard.

  5. Will Dean says:

    The following will list ‘slow’ top-level windows:  (Uses VS2005 ‘for each’ syntax)

    #include <stdio.h>

    #include <tchar.h>

    #include <windows.h>

    #include <vector>

    #include <mmsystem.h>

    #pragma comment(lib, "winmm")

    std::vector<HWND> windowHandles;

    static BOOL CALLBACK

    EnumWindowsProc(

    HWND hwnd,

    LPARAM lParam

    )

    {

    windowHandles.push_back(hwnd);

    return TRUE;

    }

    int _tmain(int argc, _TCHAR* argv[])

    {

    timeBeginPeriod(1);

    EnumWindows(EnumWindowsProc, NULL);

    _tprintf(_T("Found %d windowsn"), windowHandles.size());

    for each(HWND hWnd in windowHandles)

    {

    DWORD startTime = timeGetTime();

    DWORD result;

    SendMessageTimeout(hWnd, WM_NULL, 0, 0, SMTO_BLOCK, 1000, &result);

    DWORD messageTime = timeGetTime()-startTime;

    if(messageTime > 10)

    {

    TCHAR windowName[200];

    GetWindowText(hWnd, windowName, 199);

    DWORD processId;

    GetWindowThreadProcessId(hWnd, &processId);

    _tprintf(_T("Window ‘%s’ (procId %d) took %dms to respondn"),windowName,processId,messageTime);

    }

    }

    return 0;

    }

  6. A says:

    Money is guilty of this…

    Window ‘DBSYNCHANDLER’ (procId 2852) took 198ms to respond

    Window ‘Money – Microsoft Money’ (procId 2852) took 200ms to respond

    Window ‘Money Scheduler’ (procId 2852) took 201ms to respond

    Window ‘DDE Server Window’ (procId 2852) took 201ms to respond

    Window ” (procId 2852) took 201ms to respond

    Window ” (procId 2852) took 200ms to respond

  7. Steve says:

    Looks like Microsoft’s Antispyware is even more guilty:

    Window ‘gcasServ’ (procId 3184) took 293ms to respond

    Window ” (procId 3184) took 500ms to respond

    Window ‘Giant AntiSpyware Service’ (procId 3184) took 500ms to respond

    Window ‘Default IME’ (procId 3184) took 495ms to respond

    Note that gcasServ is also Giant Antispyware (aka, Microsoft Antispyware).

  8. I find it curious that people like to point out that Microsoft software suffers from various issues, but they don’t bother pointing out all the non-Microsoft software with the same problem. It’s not like I claimed that all Microsoft software was perfect. Do people just get a thrill out of pointing the finger at MS?

  9. Gabe says:

    I don’t understand what sort of event is being checked for by these invisible windows.

    What could you possibly need to check for that couldn’t just be solved with a mutex, event, or window message?

  10. Scott says:

    <i>Do people just get a thrill out of pointing the finger at MS?</i>

    People expect the MS developers to know what they’re doing, while they know that other software developers don’t and don’t expect much.

  11. Hate to burst your bubble, but Microsoft programmers are programmers not gods.

  12. I’m surprised that a thread can tie up the whole user interface in such a trivial way. Or am I?

  13. steven says:

    I’m suffering from the same problem PatriotB mentions in his first post. It’s rather annoying having explorer freeze for several minutes when I simply wanted to start Notepad by pressing Ctrl-Alt-N. It happens on all my Windows installs (from 95 through XP). The program Will Dean posted only tells me that explorer.exe doesn’t respond during that time, nothing else. (No non-responsive windows when I don’t hit a shortcut hotkey).

    Any way I might figure out what the culprit is?

  14. A says:

    I find it curious that people like to point out that Microsoft software suffers from various issues, but they don’t bother pointing out all the non-Microsoft software with the same problem.

    Because I’m not aware of any. Money is the only program I use that causes Explorer to hang for several seconds every time I press a shortcut hotkey.

  15. I discussed broadcasts last year (June 27).

    If you want to debug the problem further, then go for it, don’t be shy. Get the thread that is not responding and take a stack trace and do some analysis.

  16. Um, only programmers in the Windows division get access to Windows source code. Everybody else has to fight with Windows like a normal ISV.

  17. J says:

    The real answer to your question, Raymond, can be found in the descriptive text on this page:

    http://samvak.tripod.com/abusefamily16.html

    There’s no empathy toward Microsoft developers because of extreme hate these people feel about the company.  These people feel threatened by your blog because they see you as Microsoft telling them how to think and how to act.  They feel that it is their responsibility to point out to all that Microsoft is not the messiah of software development.  Nevermind that normal people come here for insightful discussion of engineering topics.  The lack of empathy makes these people blind to the fact that Microsoft is a normal company made up of normal software developers.  Normal software developers aren’t omnipotent!  They don’t know every part of every system that their company developed!  It’s seriously a personality disorder that makes these people act out on your blog.

    To address another point that someone made, my company has fairly small software projects.  But I’ll be damned if I’m going to go grovelling in someone else’s source code when they’ve given me an interface or platform to use instead!  I’ve got MY project to work on and a deadline to meet, thank you very much.

  18. myteron says:

    microsoft programmers are in the fortunate position of being able to see into the big black box that windows is… they see both sides of the problem wheras us mere mortals don’t. To see them *still* screw it up is therefore incredible.

  19. Will Dean says:

    "Everybody else has to fight with Windows like a normal ISV."

    I’m sorry, I don’t believe this.  I’m quite prepared to believe that the production source code isn’t generally available, but I don’t believe that (for example) the Office team’s only access to support is the same as mine.  

    Which is to pay a subcontracted call-handling company to open a support incident, and then wait for indeteminate periods while emails go unanswered, assigned (hopeless) support engineers go sick, spam filter my email, reply to questions I didn’t ask, etc. etc.

    There are frequent references on blogs.msdn.com to discussions on internal mailing aliases, internal courses, etc.  All your support engineers appear to have access to full symbols for the OS, for example.

    I don’t begrudge MS any of this – of course you should support your own staff.  What irritates me is the repeated suggestion on some of the blogs around here (particularly this one, I’m sorry to say) that the rest of us are in the same situation on the outside, and only make errors in Windows programming because we’re stupid, lazy or dishonest.

    IT’S HARDER FOR PEOPLE TO WRITE SOFTWARE FOR WINDOWS IF THEY DON’T WORK FOR MICROSOFT.

    That’s inevitable, so it shouldn’t be denied.

  20. rolfhub says:

    Are you sure you got the formatting of the code correct? The first line states "code in italics is wrong", implying that only some of the lines posted are wrong, but if you look at the HMTL source, the whole code snippet is embedded in <PRE><I>…</I></PRE>.

  21. Yup, it’s all wrong. I was just reminding readers that my rule is that code in italics should not be copied.

  22. I’m not denying that it’s easier to write Windows software if you can have lunch with the people who work on it. But it’s not the case that they can "see into the big black box". It’s still a black box to people outside the Windows division.

  23. Will Dean says:

    It’s made distinctly less black merely by having the private symbols, even if we leave out the lunch breaks with Dave Cutler.

  24. Feroze Daud says:

    It is wrong to assume that just because MS dev’s have access to the platform Dev’s, that we get some secret information that makes it easier to write software. I agree that when we need help, we might get faster responses, and that is just a factor of people working in the same company, which is true for any company out there.

    Now, I agree that you might not have gotten a satisfactory answer from MS support in some instances. However that has nothing to do with the point mentioned above. Also, if you need private symbols to debug your problem, then that means that MS has not done a good job in developing/documenting the API (which is a shame). And I hope those cases get lesser and lesser.

    Nobody’s perfect, and as other people pointed out above, MS is a very big company, and one doesnt get to be in the same corridor as Raymond to learn from his wisdom. So, yeah, we make mistakes too.

    As regards software issues, the sheer number of hacks that have gone into windows to make it backwards compatible with other apps out there should tell you that MS is not the only reason they were put in.

  25. Jerry Pisk says:

    Unfortunately what Raymond is describing here is not secret and is not supposed to be secret. It’s supposed to be the obvious to anyone writing software for Windows. But as we all know even Microsoft’s own developers do not get writing software for Microsoft’s platform well. A little of eating your own dogfood would help, of course if it gets through the horrible corporate structure any company Microsoft’s size is – which is at least imo the reason why Microsoft does not follow its own best practices. The Money project manager’s goal is to release Money and to compete against other financial software, not to write good Windows based code. Just like any other company writing code for Windows.

  26. Legolas says:

    I think that people are appaled that MS can’t write sooftware for it’s own platform correctly is that it should be quite obvious that if the people who work there can’t get it right, what hope do any of us have?

    Sure, perhaps they don’t get to see the windows source. But I’m betting that if they wanted to, getting access to the windows source program would be far less costly for them… because it would be microsoft paying microsoft. Same for access to people, support, courses etc.

    And then there is the expectation that if you are saying this here, the whole of microsoft should know already, right? Since it’s all called microsoft, people expect that you all know the same things. I know microsoft is a really big amount of people these days, and I think it is hard for most outsiders to grasp just how big.

    A question then: now that you know that Money and Microsoft (ex-Giant) Antispayware are doing it wrong, will you forward them a polite note with a link to this entry? (And will that cause them to set it right if you do?)

  27. Legolas: How do you know that Money and Microsft Anti-Spyware indeed have the problem I described here? I doubt very much that they have Sleep() loops. I suspect the problem is really something else.

  28. Norman Diamond says:

    Friday, February 10, 2006 3:58 PM by oldnewthing

    > Do people just get a thrill out of pointing

    > the finger at MS?

    Maybe some do, but some have other reasons.  Surely you know that a lot of people don’t like being told "Do as I say not as I do."  In some of your blog postings you have pointed out that your employer is included in the targets of your complaint.  Had you pointed out the same this time, I would be posting an expression of thanks, and I’ll bet you wouldn’t have got so many complaints from others.

    As for the idea that non-Windows divisions of Microsoft suffer the same problems that people outside of Microsoft suffer, well, I don’t buy it.  Here are two examples.

    Suppose an Office developer (whether you hate them or not) tries to explain to the Windows division that no, in every ANSI code page, you do not have one character always being exactly one byte.  Suppose someone in the Windows division answers saying that the developer has a misunderstanding and that in every ANSI code page you do have one character always being one byte.  Suppose the developer tries to escalate the issue by asking Microsoft to provide more information to people in the Windows division who desperately need to learn the facts.  Suppose Microsoft replies that because the developer is located in Australia (which is false) the developer will be served by Microsoft support in Microsoft Japan (which happens to be where the developer lives) and the developer should pay a fee to Microsoft Japan for support.  Now maybe Microsoft Japan has the capability to ask Microsoft management to escalate an issue in which Windows division personnel need more training, I don’t know.  But should developers pay a fee in order to try to get this done?  Would a developer in Microsoft’s Office division get treated the same way?  I really do not think so.

    Second example.  Suppose a Windows NT service pack from the Windows division (whether you hate them or not) breaks the version of Microsoft Word that is currently shipping and will continue to be the most current version for at least one more year.  Maybe it was due to a bug in Word and maybe a shim would have to be added to Windows to work around it.  Maybe it’s due to a bug in Windows and maybe the next service pack and future versions of Windows should get a fix instead of getting a half-fix and remaining permanently half-broken.  Does the Office division really get left in the same lurch as non-Microsoft people, will the bug really never get fixed?  Well when it’s Japanese Windows and Japanese Word, the answer is yes.  But if it were the US version, would the same thing happen?  The answer is no.  (Though it reverts to yes after Microsoft says that the affected versions of Word are too old.)

  29. Dean Harding says:

    To all those people complaining that Microsoft developers have it easier than the rest of us, or that being able to see the source code would make *this particular* problem a non-issue, then I challenge you to tell me how being about see the source code would let you know that you need to be constantly pumping messages.

    How would talking to the Windows’ developers over lunch make you suddenly aware that sleeping on a UI thread is a bad idea? What question would you ask the developer – if you weren’t already expecting a problem – that would lead you to this particular insight?

    Now, I agree that Microsoft programmers probably do have it much easier when it comes to developing Windows applications, but that would only be the case when there was an *obvious* problem: if you couldn’t get your program to work, then you could ask a Windows dev. But for something like this, where the problem is non-obvious, then what would be the trigger for you to even go and ask?

  30. Aaargh! says:

    I find it curious that people like to point out that

    > Microsoft software suffers from various issues,

    > but they don’t bother pointing out all the

    > non-Microsoft software with the same problem.

    Sure, but program X by obscure company Y is not used on +90% of all desktop computers.

    Furthermore there have been some quite obvious bugs in Windows that have been there since win9x and still haven’t been fixed.

    My personal most annoying bug ever:

    Try accessing a share on a SMB network where the server is slow or unable to respond, this freezes the ‘explorer’ UI until the server responds or the connection times out. It seems to me that some file access is being done in the UI thread.

    Meanwhile, both Konqueror on Linux and Finder on MacOS X remain completely responsive while trying to access a SMB server.

  31. Ashod Nakashian says:

    Now I know what Visual Studio does when I’m debugging. This same hanging problem occures when I open a DDE document when I have a paused proccess during a debugging session.

    I bet if you send the VS guys an email with a link to this page they’d get their act straight… or so I like to wish.

    -Ash

  32. Moi says:

    It’s still a black box to people outside the Windows division.

    Clearly it should be open source.

  33. Ashod: Um, it’s not VS that’s doing it. It’s your app! Since your app is broken into the debugger it can’t respond to DDE messages.

  34. Mike Dimmick says:

    Raymond: re Ashod: not necessarily, I’ve seen this behaviour while doing device debugging in VS.NET 2003, although, weirdly, only when ActiveSync has a partnership rather than being connected as a guest.

  35. mysteron says:

    obviously having access to the source would give developers a far deeper level of understanding of windows as a whole and no doubt given that, they may not make the mistake in the first place. another thing is debugging – obviously a lot easier to see what’s going on if you have all the source code.. i could go on.. it’s not very challenging really

    then I challenge you to tell me how being about see the source code would let you know that you need to be constantly pumping messages.

  36. Brad says:

    Try accessing a share on a SMB network

    > where the server is slow or unable to

    > respond, this freezes the ‘explorer’ UI

    > until the server responds or the connection

    > times out. It seems to me that some file

    > access is being done in the UI thread.

    This isn’t the only place.  Try clicking on a folder with a few hundred ZIP files in it with Windows XP.

  37. Having access to source code doesn’t teach you philosophy, which is the real issue here. It’s not like there’s a function called ThisIsWhyYouHaveToKeepPumpingMessages. Rather, the need to pump messages is a principle that guides the design decisions.

    Having the schematics to a car won’t tell you the correct way to power your mp3 player. (You may find *a* way but will it be the correct way?)

  38. Of course you’re assuming that the DirectUser code started out as Windows code. There is just one Microsoft Research division; it’s not like there’s a Windows Research division, a Messenger Research division, etc.

  39. PatriotB says:

    I’m just putting it how I see it.  Obviously, the life of source code (or even concepts, ideas, techniques) at Microsoft is much more complicated than "every product writes their own code."

    Simply put, it would’ve been great (IMHO) if Microsoft would’ve documented DirectUser.  It’s obviously technology that a number of Microsoft teams have been interested in, and it’s something that would have provided great possibilities to ISVs.

    Alas, I don’t think we’ll ever see it.  Windows Presentation Foundation provides a much richer platform for UI development and it is obvious that Microsoft wants ISVs to move in that direction.  DirectUser documentation would’ve been more useful back in 2001, when XP was released, back when Avalon was still in its infancy.

    Though, with the large amounts of new Vista code using DirectUser (task dialogs, control panel pages, IE7 tabs, and more I’m sure), it’s still a powerful technology.  And it is unmanaged code, something that many of us still develop.  Windows’s biggest strength has always been in providing a great platform for third party apps, and it’s sad when portions of code are left undocumented when they could enable so much cool stuff.

  40. Moi says:

    the need to pump messages is a principle that guides the design decisions.

    Yes. The question though is how many developers are still around who started out "the hard way" (writing C code for Windows apps) as opposed to just jumping in with Visual C++ & MFC or something like that. I hope most of the MS staff are at least "old school" in knowledge, if not in age. Or to put it another way: if tools exist that allow any idiot to create software, don’t be surprised if any idiot does.

  41. . says:

    > There is just one Microsoft Research division; it’s not like there’s a Windows Research division, a Messenger Research division, etc.

    One more reason to enforce a split of MS in two companies.

  42. PatriotB says:

    "Um, only programmers in the Windows division get access to Windows source code."

    Unless you’re MSN Messenger, in which case you can "borrow" the Windows DirectUser code, put it in your binaries, and use it to develop your app’s user interfaces.  (Full disclosure: I obviously don’t have access to the source for either the DirectUser API or MSN Messenger, so I don’t have concrete evidence.  But both use the window class "DirectUIHWND" and are too similar to be "independently developed" code.)

    IE7 is doing this as well, taking parts of duser.dll and putting it in ieui.dll.  Of course, IE is part of the Windows division, so it is perfectly OK for them to have access to the code.  But copying the code gives them an unfair advantage over third-party browser makers–an unfair advantage that the antitrust settlement is supposed to eliminate.

    Initially, the IE7 Beta 1 used duser.dll directly, in violation of the antitrust settlement, since the DirectUser API isn’t documented.  So rather than publicly document DirectUser, someone decided to take parts of the duser.dll code and put it into a new DLL, ieui.dll.  Now they can say, IE7 isn’t using any undocumented APIs.  Instead, they took a chunk of non-IE Windows source code and copied it into a private DLL that can be called part of IE.  Following the settlement to the *letter*, but certainly not the spirit.

  43. Because it didn’t actually help any, and it encouraged bad code.

  44. Dan McKinley says:

    Blocked finalizer threads have gotten some recent publicity on Tess Ferrandez’s blog. I recently ran…

Comments are closed.