惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
博客园 - 三生石上(FineUI控件)
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
V
Visual Studio Blog
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
MongoDB | Blog
MongoDB | Blog
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 【当耐特】
Microsoft Azure Blog
Microsoft Azure Blog
The Cloudflare Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Engineering at Meta
Engineering at Meta
L
LangChain Blog
Martin Fowler
Martin Fowler
GbyAI
GbyAI
博客园 - 司徒正美

The Old New Thing

Why didn't Read­Directory­ChangesW provide a way to correlate the two sides of a rename operation? - The Old New Thing How can I remove the Close button from my window caption? - The Old New Thing Why is the x86 undefined instruction called ud2? Why 2? - The Old New Thing What algorithm did Windows XP use to choose your initial user picture? - The Old New Thing A sample use of the winstart.bat file in Windows 95 - The Old New Thing Why don't we allow stacks to be sparse, instead of forcing them to be contiguous? - The Old New Thing What happens if you change a window class's GCL_CB­WND­EXTRA? - The Old New Thing The case of the progress callback that never got called when progress happened - The Old New Thing The perils of binding to value types in XAML - The Old New Thing Microspeak: Funded / unfunded - The Old New Thing AWE does not require PAE, though PAE makes it much more useful - The Old New Thing On forcing all derived classes to implement a specific non-virtual method, part 2 - The Old New Thing On forcing all derived classes to implement a specific non-virtual method, part 1 - The Old New Thing In the product end game, every change carries significant risk, episode 2 - The Old New Thing Why didn't the Windows Entertainment Pack just run the MS-DOS version inside an emulator? - The Old New Thing Comparing the two holograms on the Windows 95 box - The Old New Thing Reducing C++ template bloat by factoring out the type-dependent portions of the function, practical exam - The Old New Thing Reducing C++ template bloat by factoring out the type-dependent portions of the function - The Old New Thing On wrapping a callable in a lambda that just calls it with the same parameters - The Old New Thing Why did the Microsoft Entertainment Pack for Windows have a special sticker announcing that it also had Tetris? - The Old New Thing How do functions like alloca allocate memory from the stack? - The Old New Thing How do functions like alloca allocate memory from the stack? - The Old New Thing Forcing an ARM64X executable to run as a specific architecture - The Old New Thing A little helper class for managing LPPROC_THREAD_ATTRIBUTE_LISTs - The Old New Thing The comments that go into code versus those that go into the pull request description - The Old New Thing The little-known winstart.bat batch file - The Old New Thing How can I perform a Copy­File&shy in unbuffered mode? - The Old New Thing Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 5 - The Old New Thing Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 4 - The Old New Thing Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 3 - The Old New Thing
Why do you say that a COM STA thread must pump messages i...
Raymond Chen · 2026-05-22 · via The Old New Thing

One of the rules for COM single-threaded apartments (STA) is that the thread in that apartment must pump messages. But we also see code that initializes COM in single-threaded mode but which never pumps messages. Consider this function from the XML DOM object dynamic creation sample:

int __cdecl wmain()
{
    HRESULT hr = CoInitialize(NULL);
    if (SUCCEEDED(hr))
    {
        dynamDOM();
        CoUninitialize();
    }
    return 0;
}

The CoInitialize function initializes COM in single-threaded apartment mode, and then the program does some work, and then it uninitializes COM, and it never pumps messages. What gives? Shouldn’t there be a message loop?

The rule about single-threaded apartments is that they must pump messages when idle. If they are busy doing something, then clearly they can’t pump messages because they are busy doing something!¹

If your thread initializes COM as a single-threaded apartment, and then does a bunch of work, and then uninitializes COM, then that’s great. Your thread was never idle, so it never got a chance to pump messages. (Though if your thread made COM calls out to other threads, COM will pump messages while waiting for the reply, so it did pump messages while the thread was idle.)

Failing to pump messages when idle means that when another thread wants to communicate with your thread, it never gets a response. Now, if your thread is busy, then it’s fine that the other thread doesn’t get a response from you—you’re busy with something else after all. But if you are in a single-threaded COM apartment and you have finished with whatever you’re doing, you need to pump messages to see if there’s any work that COM wants you to do, or you need to uninitialize COM.

Now, you might say, “Look, my thread doesn’t create any windows, and it doesn’t do any cross-thread COM stuff, so who cares that it’s not pumping messages? It’s not like anybody is ever going to ask this thread to do anything, and since it created no windows, nobody could send it anything.”

Aha, but you see, your thread did create a window. When you initialize a thread as a single-threaded apartment, COM creates a window. It creates this window so that it can receive inbound requests for the thread to do something. If you don’t pump messages, then you have a thread blocked not pumping messages, which will jam up window broadcasts.

¹ An intentionally obtuse interpretation of the rule that “an STA thread must pump messages” would be that your thread can’t do anything except call GetMessage and DispatchMessage! Because any other line of code would not be “pumping messages”.

Category

Topics

Author

Raymond Chen

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.