RegNotifyChangeKeyValue sucks less


One of the gotchas of the Reg­Notify­Change­Key­Value function is that the notification registration has thread affinity. This is a problem if you want the notification registration to outlive the thread that generated it. In particular, if you register the notification from a nonpersistent thread pool thread, you get into an infinite loop:

  1. Thread pool task calls Reg­Notify­Change­Key­Value, and waits for the associated event via Register­Wait­For­Single­Object.
  2. Thread pool thread goes idle.
  3. Thread pool destroys the idle thread.
  4. Due to thread affinity, this signals the handle.
  5. The thread pool queues a task to process the handle that was signaled.
  6. The task checks the registry key (observes that nothing changed) and calls Reg­Notify­Change­Key­Value again.
  7. Repeat.

Windows 8 added a new flag to the Reg­Notify­Change­Key­Value function: REG_NOTIFY_THREAD_AGNOSTIC. If you pass this flag, then the notification registration does not have thread affinity. If the thread that called Reg­Notify­Change­Key­Value exits, the notification registration remains active.

Comments (11)
  1. Bradley says:

    Is there any benefit to calling it with thread affinity?

  2. Joshua says:

    > Windows 8 added ...

    Which means 10 years before we can use it. The Old New Thing is aptly named.

    We might as well consider it a law of computing. 10 years must pass between when MS adds a kernel-level feature and Enterprise-grade commercial software can take advantage of it.

  3. Colin says:

    @Joshua so um don't use a thread pool

  4. Gabe says:

    I wonder if there's anybody who can explain the thread affinity aspects of this API. I don't see why it would have it in the first place.

    I also don't understand why you'd need a flag to make it agnostic -- surely any program that operates correctly with affinity will operate correctly without affinity, right? I'd hate to imagine there are programs that rely on spurious event signals when threads exit.

  5. > surely any program that operates correctly with affinity will operate correctly without affinity, right?

    Sure, but if the program was OK with affinity, the OS can free up the notification resources when the thread exits. If the program requested REG_NOTIFY_THREAD_AGNOSTIC, the OS has to keep those resources until the key handle is closed.

  6. jvert says:

    @Gabe, Originally this API was modeled after the async I/O pattern. You could think of it as queuing an async read which completes when the notification fires. Async I/O has the same thread affinity behavior. In retrospect, maybe not the best decision, but that is the rationale.

    Note this API dates from NT3.1 around 1992 and predates things like thread pools and completion ports.

  7. Ken Hagan says:

    @Joshua: You have a point, but if Win10 really is offered a free upgrade for Win7 onwards (at least on client machines, not servers) then actually you probably can start writing software to the Win10 API next year.

  8. JM says:

    @jvert: for "async I/O", read "alertable I/O". Asynchronous I/O is the umbrella term.

  9. voo says:

    @Ken Hagan: It must be nice not writing any business software.

  10. jas88 says:

    What would be nice here is some sort of backwards compatibility shim - so we could all use "Reg­Notify­Change­Key­ValueThreadAgnostic", which on Windows 8+ is a straight API call, and on earlier versions provides an equivalent through a wrapper (maybe routing the Reg­Notify­Change­Key­Value call to a compatibility worker thread, which can then use its own event and signal the event passed).

    It's something I like from the web development field: rather than coding for the lowest common denominator across the board, code for newer facilities then use some sort of polyfill to compensate on older platforms. Better for the legacy platforms to bear the burden of obsolescence, rather than hold everyone else back!

    @voo: It seems a shame for Microsoft to improve the API like this - only for us to have to ignore it for years because it's not back-ported. On the other hand, I suppose for some business software, you could just keep selling the Windows 7 era software to Windows 7 users, while you develop new versions for Windows 10: unless it's something like accountancy, where the tax rules change regularly so you have to stay current, will many companies that refuse to upgrade other software be a good market for upgrades to your own?

  11. Anonymous Coward says:

    @jas88: *Most* new features in *most* APIs (that aren't under your control) can't be used for some time until all of your customers have upgraded. That doesn't mean that they shouldn't get new features - having the feature in 5 years is better than never having the feature.

Comments are closed.

Skip to main content