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 SuppressBackgroundThread
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 NotificationHook
function before your message loop and the NotificationUnhook
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_
SETTINGSCHANGE
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 SuppressBackgroundThread
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.
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...
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.
The link at the bottom of the linked article (linkception?) is broken. http://blogs.msdn.com/oldnewthing/archive/2006/01/26/517849.aspx gives a 403 Forbidden error.
They have allegedly been working on this broken links for a long time now. I’ll ping them again.
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.
Funnily enough (lol, not really).
We just had an issue with the GdiplusStartup and the SuppressBackgroundThread flag (related to DDE operations)
https://docs.microsoft.com/en-us/cpp/mfc/special-cwinapp-services?redirectedfrom=MSDN&view=vs-2019