Invalid thread and process IDs

Perhaps you want a value to use as a sentinel, which you want to be guaranteed is never a valid thread ID or process ID. What values can you use?

Nothing is explicitly written about this topic, but you can put on your logic cap and figure it out.

If you need an invalid thread ID, you can use zero. How do you know that zero is an invalid thread ID? It's implied by SetWindowsHookEx: Notice that if you pass zero, then the hook is installed into all threads on the current desktop. This implies that zero is not itself a valid thread ID.

This sentinel value is confirmed by GetThreadID, which uses zero as its error return value.

Similarly, if you need an invalid process ID, you can use (DWORD)-1. This comes from AllowSetForegroundWindow: The value ASFW_ANY has special meaning, which implies that it is never a valid process ID.

Or, you can use zero as your invalid process ID, since that is the error value returned by GetProcessId and GetProcessIdOfThread.

Comments (21)
  1. William Adams says:

    You might have problems with these assumptions when the CLR is running in different host environments, like SQL Server.

  2. Raymond Chen says:

    CLR threads are not the same as Win32 threads. I’m talking about Win32 threads here.

  3. Dmitriy Zaslavskiy says:


    Please talk (blog) about threading affinity for user code. I asked about that before. Perhaps you forgot. It’s important to .NET world as well because for example one would not be allowed to DestroyWindows in finalizers.

    Thank you very much for your blog.

  4. Raymond Chen says:

    I assure you, thread affinity is on my very long list of things to write about (80 topics and growing). Please be patient. The more complicated topics take longer to write about.

  5. B.Y. says:

    Maybe you should publish your list of topics, and we can vote on which ones we want to read about, or don’t want to read about.

  6. Raymond Chen says:

    This isn’t a democracy. I write about what I want to write about. If it happens to coincide with what you want to read, that’s just a nice side-effect. Besides a lot of my topics are just memory-joggers. For example two entries are "fibers" and "scrollbar gutter".

  7. eaw says:

    am I the only one missing the history blogs?

    I remember once an irresistable look into MS’s history. Lately, the "history" section seems more similar to the "code" section.

    I don’t mean to be a whiner, but I really enjoyed the more accessible MS trivia that seems less common lately.

  8. Raymond Chen says:

    History is harder to write.

  9. Craig says:

    But…if you write history, it will always be kind to you :-)

  10. runtime says:

    Don’t write history, make it! ;-)

    Raymond, I look forward to your discussion of NT fibers. Most books say fibers were only introduced (by Dave Cutler?) for porting Unix code that relied on user-level threads, but I think user-level threads could have performance advantages for any Windows app. How do fibers make porting Unix code easier than using regular NT kernel threads? How does one debug fibers from MSDEV?

  11. Frederik Slijkerman says:

    I would love to hear about fibers; I’ve never understood why anyone would want to use them!

  12. Raymond Chen says:

    I’ve been working on the discussion of fibers for over a week. It’s a very simple idea but if I just said what it was, people would say, "I still don’t understand", so I have to go into a lot more detail. It’ll probably take up over a week of blog entries just to go into the detail people will want.

  13. Dan Maas says:

    I wish you had time to write a book Raymond (or several books :). Your in-depth discussions are a good complement to the sometimes-inscrutable MS developer documentation.

  14. Andreas Häber says:

    Chris Brumme writes a lot about how Microsoft SQL Server uses fibers in his post about hosting the CLR ( His post is not directly about fibers, but there is a lot of information about it due to the discussion about MS SQL Server.

    But maybe the most important part in the article, with regards to fibers, is his first paragraph in this comment: ;)

    But a more direct discussion about fibers would be great to read :)

  15. keithmo [exmsft] says:

    IIRC, process IDs and thread IDs come from a single, globally shared "ID space". Is this fact actually documented anywhere?

  16. Christian says:

    Raymond, please write about what YOU want when YOU have the time and WANT to write. I really enjoy reading your blog and I’m always happy to find new articles in my aggreagator.

    But the recent things like the whining in these comments and the comment spam and so on don’t look too motivating for you…

  17. Raymond Chen says:

    I already discussed why I’m doing this instead of writing a book.

    If this ever turns into a book, I’ll try to make it one of those cute 170-page books like the ones Jon Bentley writes.

  18. Mike Dimmick says:

    keithmo: It’s certainly documented in ‘Inside Windows 2000’, but it’s probably not something you should rely on. I don’t think it’s documented anywhere on MSDN.

    Basically, anything you find in an "Inside" book should be considered changeable, IMO. It might help you in debugging, but you should pretend there’s a Chinese Wall.

  19. Henk Devos says:

    If you are talking about a sentinal to detect memory corruption (buffer overflow etc) then NULL would be the very last value to use.

  20. Raymond Chen says:

    I mean a sentinel to be used, for example, in a m_dwThreadId variable to indicate "There is no thread ID."

Comments are closed.