October 29th, 2019

If you suppress GDI+ background thread, then you are expected to pump messages yourself

When you initialize GDI+ by calling GdiplusStartup, you can choose to let GDI+ create its own notification thread (also know as the background thread), or you can suppress the notification thread and promise to do the work yourself. If you choose to do the work yourself, by setting Suppress­Background­Thread to TRUE, then the documentation says,

Call the hook and unhook functions before and after the application’s main message loop; that is, a message loop that is active for the lifetime of GDI+.

In order to successfully put the Notification­Hook function before your message loop and the Notification­Unhook function after it, you need to have a message loop to begin with.

The reason for the message loop is that GDI+ needs a helper window in order to listen for things like WM_SETTINGS­CHANGE messages so it knows when to invalidate its caches or adjust its behavior depending on things like whether the session is on the console or is redirected via Remote Desktop. And that helper window needs a message loop so it can process messages.

Normally, this helper window goes on the notification thread, but you can assume responsibility for the helper window, and it will go onto your thread, which by virtue of now being a UI thread, must pump messages. The idea is that your application probably already has a UI thread, so you may as well add the notification window to that thread. That way, you save a thread.

Unfortunately, some people didn’t quite understand this point. They saw the Suppress­Background­Thread option and said, “Hey, if I set this value to TRUE, then I save a thread!” They didn’t read to the part where it says that you need to put a message loop on that thread.

The result is that the next time the system sends a message to the helper window, the helper window cannot receive the message because the thread isn’t pumping messages, resulting in the usual negative consequences.

Next time, we’ll look more closely at one of those negative consequences.

 

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

6 comments

Discussion is closed. Login to edit/delete existing comments.

Newest
Newest
Popular
Oldest
  • Kalle Niemitalo

    If you suppress the background thread, then how does GDI+ decide which thread should create the notification window?

    Is it the thread that calls GdiplusStartup? However, the same thread is not required to call GdiplusShutdown, and the documentation does not say that the thread even needs to be kept alive.

    Is it the thread that calls NotificationHook? However, you described that GDI+ created the notification window even though the application failed to call NotificationHook.

    This reminds me about...

    Read more
  • Joe Beans

    It’s a shame so many API and framework threads are wasted listening for a single event. .NET and the shell namespace are horrible at that, then you have Job object notifications which need their own IOCP. I wish that more if not all notifications and continuations were posted to the default thread pool. I know that several Win32 functions like GetAddrInfoEx are doing this.

    • Raymond ChenMicrosoft employee Author

      They have allegedly been working on this broken links for a long time now. I’ll ping them again.

      • cheong00

        In fact, most of the old links are broken.

        Say, the link on that linked post: We looked at this a little while ago.

        http://blogs.msdn.com/oldnewthing/archive/2006/01/26/517849.aspx

        Should be pointing to:

        https://devblogs.microsoft.com/oldnewthing/20060126-00/?p=32513

        The problem is on deducing what is the value behind "p".

        I found that by visiting the link for the date https://devblogs.microsoft.com/oldnewthing/20060126-00/ I can see the articles posted on that date, but obviously this won't work for auto-correcting the links on posts.

        Read more

Feedback