WaitForInputIdle should really be called WaitForProcessStartupComplete


The WaitForInputIdle function waits for a process to finish its initialization, which is determined when it reaches a state where it is just sitting around waiting for messages.

The documentation for WaitForInputIdle doesn't even get around to the initialization part until the Remarks section. If all you read is the one-sentence summary, Waits until the specified process is waiting for user input with no input pending, or until the time-out interval has elapsed, it would not be unreasonable for you to conclude that a process goes into and out of the input idle state each time it processes a message. But no, it's a one-time transition.

If you call WaitForInputIdle on a process which had previously gone input idle, but is now busy and not processing pending input messages, the function will still return immediately, because WaitForInputIdle only checks whether the process has gone input idle at all and not whether it is input idle right now.

As the Remarks section notes, the purpose of the WaitForInputIdle function is for a process to determine whether another process (which is recently launched) has reached a state where it is okay to send that process messages. This is important to know when the form of communication between two processes is a message-based mechanism, and the two processes otherwise have no real way of knowing what the other is doing. (If the two processes had been written by the same author, then you could come up with some more expressive interface for the two to communicate through, one which avoids the need for one process to guess when the other one is ready.) The specific scenario that WaitForInputIdle was created to address is DDE.

Back in the old 16-bit days, you didn't need a WaitForInputIdle function, because scheduling was co-operative. You know that the other process was sitting idle, because if it were busy, your code wouldn't be running in the first place. It's like waiting for the talking stick to be handed to you so that you can ask the question, "Are you ready to give up the talking stick?" The WaitForInputIdle function assisted in the porting of these 16-bit applications by allowing a process to wait and simulate the "Wait for the other person to stop talking" operation which had previously been implicit in a co-operative system.

What would it mean for WaitForInputIdle to wait on a program that has already completed its initialization, when the program has multiple threads? Suppose one thread is sitting around waiting for messages, but another is busy and still has unprocessed input messages. Would a call to this WaitForInputIdleAgain function wait, or should it return immediately? According to the description, it would return immediately, because there is a thread in the process which is "waiting for user input with no input pending." So even if WaitForInputIdle worked like this imaginary WaitForInputIdleAgain function, it still wouldn't help you, because it wouldn't actually wait in cases where you probably wanted it to.

Actually, the above analysis applies to WaitForInputIdle as well; we'll pick up this discussion next time.

Comments (24)
  1. SSLaks says:

    You have a mistake in your last sentence.

  2. Carl D says:

    Presumably you meant to name a different function in the last sentence…

    [Um, I’m not seeing it… -Raymond]
  3. Arno says:

    I found this function to be problematic. Any program making COM calls is often agnostic whether it is calling an in-process or out-of-process server. Dispatching synchronous out-of-process COM calls means running a modal loop, which triggers WaitForInputIdle to report that start-up is done :-( To know whether a program is making COM calls is tough in today’s environment of "mash-up" applications with add-ins and little system tools injecting DLLs into processes. In short, WaitForInputIdle is brittle.

  4. Ivo says:

    If WaitForInputIdle should really be called WaitForProcessStartupComplete, does that mean it works for console applications without a message queue?

    [Given that it’s a window manager function, it naturally applies only to GUI programs. I guess nitpickers would prefer that it be called WaitForGUIProcessStartupComplete. -Raymond]
  5. Yuhong Bao says:

    "If WaitForInputIdle should really be called WaitForProcessStartupComplete, does that mean it works for console applications without a message queue?

    Nope, WaitForInputIdle is only for GUI apps that uses window messages.

  6. ggeldorp says:

    If you really do need to process some messages without unblocking the WaitForInputIdle() caller you can use PeekMessage with the PM_NOYIELD flag.

  7. Rob says:

    @Arno, I think the quote “The WaitForInputIdle function assisted in the porting of these 16-bit applications” for Raymond’s article suggests, at least to me anyway, that WaitForInputIdle was intended to help applications migrating from Win16 to Win32, so probably isn’t the right answer for a “true” 32-bit app – especially in light of the points you’ve made..

    [What he said. In fact, I wrote something even stronger: It’s to assist in porting 16-bit programs which used DDE to 32-bit. -Raymond]
  8. SSLaks says:

    The last sentence states

    Actually, the above analysis applies to WaitForInputIdle as well; we’ll pick up this discussion next time.

    The whole article is already about WaitForInputIdle; what will you pick up next time?

    [s/the above analysis/the analysis of the imaginary WaitForInputIdleAgain function in the previous paragraph/ -Raymond]
  9. gerald says:

    Probably that WaitForInputIdle doesn’t help you if the target application has more than one thread?

    Really, the other comments suggest that Raymond wrote that sentence as it is on purpose. Let’s just be patient.

  10. Alexandre Grigoriev says:

    There are also problems when some DLL (GDI+?)creates a thread with a message pump. That can cause premature return of WaitForInputIdle.

  11. SuperKoko says:

    Isn’t WaitForInputIdle used by Windows Explorer to display a hourglass+cursor pointer during program startup?

  12. Igor Levicki says:

    It must be that Windows 7 calls WaitForInputIdle() internally to determine whether the user is idle, because it happens to me that while I am in a full screen game reading some text the OS starts doing its background, performance killing tasks such as indexing, super-fetching, defragmenting, etc.

    The problem with OS idle metrics in its current implementation is that it assumes that "no input" must mean "no user in front of the computer, I can do whatever I want".

  13. Yuhong Bao says:

    "Dispatching synchronous out-of-process COM calls means running a modal loop, which triggers WaitForInputIdle to report that start-up is done"

    "There are also problems when some DLL (GDI+?)creates a thread with a message pump. That can cause premature return of WaitForInputIdle."

    The code doing the pumping could have avoided this by using PM_NOYIELD in the PeekMessage call.

  14. Arno says:

    Ah, now I remember why this breaking of WaitForInputIdle for COM made me a bit mad: COM does not set PM_NOYIELD, which IMO is simply wrong. When an application is waiting for a synchronous COM call to return, it has not finished startup yet, and COM should say so.

  15. JJJ says:

    @Igor Levicki:  The first half of today’s post was for Raymond to explain how WaitForInputIdle has absolutely nothing to do with determining whether a user is idle.  So no.  No, Windows 7 does not use WaitForInputIdle to determine whether a user is idle.

    Way to use it to springboard into an off-topic gripe, though.

  16. Alexandre Grigoriev says:

    @youhong2,

    PM_NOYIELD flag only exists for PeekMessage. It doesn’t exist for GetMessage or WaitMessage.

    [And besides, how would COM know when to use PM_NOYIELD and when not to? -Raymond]
  17. Mike Dimmick says:

    @Arno: but COM is pumping messages while waiting for a reply from the out-of-process call. Any queued messages to do with window creation have been dispatched. Your application will receive DDE-related messages, therefore it is idle by Windows definition.

    If you don’t want this behaviour, don’t make any outbound COM calls before you enter your main message pump. Or use COINIT_MULTITHREADED, I guess, but that won’t work very well if you use any COM objects on your initial thread.

    Your application startup code should be endeavouring to get a window up and into the main message pump, responding to the user, as quickly as possible anyway.

    @Igor Levicki: GetLastInputInfo() gives a session wide indicator of the last time input arrived. The game should probably be calling SetThreadExecutionState to tell Windows that it’s doing something important and now isn’t the time to be doing background tasks.

  18. dolph says:

    SuperKoko: no.  see STARTF_FORCEOFFFEEDBACK in the documentation for STARTUPINFO

  19. Médinoc says:

    “You know that the other process was sitting idle, because if it were busy, your code wouldn’t be running in the first place.”

    What if said other process was in the middle of a SendMessage() call but had not yet started its own message loop?

    [Think it through: Why would that DDE server send you a message at startup? It must have special knowledge about you, which means that you and the DDE server are in cahoots, in which case you have no need for WaitForInputIdle. -Raymond]
  20. Yuhong Bao says:

    [And besides, how would COM know when to use PM_NOYIELD and when not to? -Raymond]

    It is always OK, using it will have no effect if the application is already input idle.

    [Um, but what about the other side-efects of not yielding? (Like, say, not yielding? The caller might be a 16-bit app.) -Raymond]
  21. Arno says:

    @Mike Dimmick and @Raymond:

    I guess the question hinges on whether 16-bit COM allowed receiving DDE calls while COM calls were dispatched. I guess the answer is no, because multitasking was cooperative, right? So while the COM call was processed elsewhere, the caller simply stood still. Thus, PeekMessage inside a COM modal loop should set PM_NOYIELD, or not?

    [I think your attempt to address the symptom is killing the patient. Imagine what would have happened if 16-bit COM never yielded in its modal loop. -Raymond]
  22. Arno says:

    I did some 16-bit Windows programming, but never with COM. I thought that the model when doing a COM call was simply to switch over to the process receiving the call, and on completion, switch back to the process that initiated the call. So of course a COM call yielded to the receiver of the call. But did it process incoming DDE requests?

    [And how did it switch out and back? Window messages. The underlying question is moot. No sane app created cross-process COM objects as part of their startup code, so whether it worked or not is irrelevant. -Raymond]
  23. Arno says:

    I don’t want to nit-pick, but the reason I had to abandon WaitForInputIdle was that a 3rd party Excel add-in did long (10 seconds and more) out-of-process COM calls in its start-up code, making Excel input-idle prematurely.

    I understand that WaitForInputIdle is de-facto deprecated, in particular for applications that allow add-ins. Please encourage the documentation team to say so.

  24. 640k says:

    [Um, but what about the other side-efects of not yielding? (Like, say, not yielding? The caller might be a 16-bit app.) -Raymond]

    No. Not in 64-bit windows which disallow 16-bit apps from executing. COM64 could do the right thing, but it doesn’t.

    [“Hey, in order to encourage people to port their apps to 64-bit, let’s introduce more differences between 32-bit and 64-bit!” And wow, look at all those 64-bit apps we have! Um… -Raymond]

Comments are closed.