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

推荐订阅源

S
Security Affairs
S
Schneier on Security
T
Tenable Blog
G
GRAHAM CLULEY
Latest news
Latest news
D
Darknet – Hacking Tools, Hacker News & Cyber Security
A
Arctic Wolf
I
Intezer
Cyberwarzone
Cyberwarzone
T
The Exploit Database - CXSecurity.com
T
Tailwind CSS Blog
K
Kaspersky official blog
Blog — PlanetScale
Blog — PlanetScale
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Threat Research - Cisco Blogs
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
P
Palo Alto Networks Blog
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
The Cloudflare Blog
Help Net Security
Help Net Security
罗磊的独立博客
博客园 - 聂微东
Jina AI
Jina AI
Project Zero
Project Zero
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LINUX DO - 最新话题
V
V2EX
人人都是产品经理
人人都是产品经理
美团技术团队
博客园 - 【当耐特】
Spread Privacy
Spread Privacy
J
Java Code Geeks
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Security Latest
Security Latest
The Last Watchdog
The Last Watchdog
Stack Overflow Blog
Stack Overflow Blog
雷峰网
雷峰网
S
Securelist
Forbes - Security
Forbes - Security
博客园 - 三生石上(FineUI控件)
Microsoft Azure Blog
Microsoft Azure Blog
P
Privacy International News Feed
宝玉的分享
宝玉的分享
C
CERT Recently Published Vulnerability Notes

The Old New Thing

Why has the display control panel pointer truncation bug gone unfixed for so long? - The Old New Thing Speculating on how the buggy control panel extension truncated a value that it had right in front of it - The Old New Thing The case of the invalid function pointer when shutting down the display control panel - The Old New Thing Microspeak: Double-click and drill down - The Old New Thing Why don't we just make the entire stack out of guard pages? - The Old New Thing The case of the mysterious changes to integers when there shouldn't have been any code generation effect - The Old New Thing I've decoded a #pragma detect_mismatch error and fixed the mismatch, but I still get the error - The Old New Thing The other kind of control flow guard check: The combined validate and call - The Old New Thing How did Windows 95 decide that a setup program ran? - The Old New Thing I opened a file with FILE_FLAG_DELETE_ON_CLOSE, but now I changed my mind - The Old New Thing How did we conclude that CcNamespace.dll was the ringleader of a group of DLLs that unloaded prematurely? - The Old New Thing The case of the thread executing from an unloaded third-party DLL - The Old New Thing It rather involved being on the other side of this airtight hatchway: Changing administrative settings - The Old New Thing 2026 mid-year link clearance - The Old New Thing A compatibility note on the abuse of Windows window class extra bytes - The Old New Thing The evolution of window and class extra bytes in Windows - The Old New Thing The case of the DLL that was not present in memory despite not being formally unloaded, part 2 - The Old New Thing Raymond's hot take on Hainanese chicken - The Old New Thing The case of the DLL that was not present in memory despite not being formally unloaded, part 1 - The Old New Thing Cancellation of Windows Runtime activities is asynchronous - The Old New Thing Microspeak elaborated: Isn't escrow just a release candidate by another name? - The Old New Thing In memory of the man who put red and green squiggles under words - The Old New Thing What does it mean when the bottom bit of my HMODULE is set? - The Old New Thing Why doesn't Get­Last­Input­Info() return info for the user I'm impersonating? - The Old New Thing Windows stack limit checking retrospective, follow-up - The Old New Thing Retrofitting the WM_COPY­DATA message onto Windows 3.1 - The Old New Thing The time the x86 emulator team found code so bad that they fixed it during emulation - The Old New Thing How can I schedule work on a thread pool with low latency? Understanding the rationale behind a rule when trying to circumvent it What’s the opposite of Clip­Cursor that lets me exclude the cursor from a region? The Microsoft Company Party where everybody played name tag swap Rotation revisited: Shuffling more than three blocks, and other small notes The back cover of C++: The Programming Language also raises questions not answered by the front cover Rotation revisited: Avoiding having to calculate the gcd when doing cycle decomposition Rotation revisited: Cycle decomposition in clang’s libcxx Rotation revisited: A shocking discovery about gcc’s unidirectional rotation algorithm Rotation revisited: Another unidirectional algorithm The placeholder name for the Windows 8 experience was “modern” Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 3 Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 2 Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 1 A hypothetical redesign of System.Diagnostics.Process to avoid confusion over properties that are valid only when you are the one who called Start Why do you say that a COM STA thread must pump messages if I see sample code creating STA threads and not pumping messages? How do I use Win32 structures from the Windows Runtime? What is the history of the ERROR_ARENA_TRASHED error code? The classic TreeView control lets me sort by name or by lParam, but why not both? Just shows that nobody cares about debugging the parity flag any more The case of the Create­File­Mapping that always reported ERROR_ALREADY_EXISTS
If C# and JavaScript lets me await a Windows Runtime asynchronous operation more than once, why not C++/WinRT?
Raymond Chen · 2026-05-26 · via The Old New Thing

The Windows Runtime expresses asynchronous execution in the form of types like IAsyncOperation. Different languages choose to represent this concept in different ways.

  • C# wraps it inside a System.Threading.Tasks.Task.
  • JavaScript wraps it inside a Promise.
  • Python wraps it inside an asyncio.Future.

All of the above wrappers support multiple continuations, which means that you can call await on them multiple times.

But C++/WinRT doesn’t provide such a wrapper. C++/WinRT just exposes the original IAsyncOperation. The IAsyncOperation doesn’t allow multiple continuations to be attached, so you cannot co_await it multiple times.

Boo.

Why doesn’t C++/WinRT get with the program and provide a wrapper that supports multiple continuations?

Well, one reason is that C#’s System.Threading.Tasks.Task, JavaScript’s Promise, and Python’s asyncio.Future are part of the respective languages’ standard libraries. This makes them an obvious choice for projection since they are a way to represent asynchronous execution that is universally understood by anybody writing code in that language. Furthermore, the fact that they are standard library features lets the projections build on the work of others: The standard library maintainers have already implemented, tested, and optimized these classes.

C++ does not have a standard library for asynchronous execution. Instead, C++ provides raw materials out of which you can write your own library. And we wrote one such library back when we learned about C++ coroutines and implemented a simple_task class.

The lack of a standard library task type means that there isn’t a pre-existing wrapper that C++ projections could take advantage of. It’s every man for himself.

C++/WinRT provides a minimal coroutine promise for IAsyncOperation in deference to the general C++ principle of “you don’t pay for what you don’t use.” The overwhelming majority of the time, you have no need to await an IAsyncOperation more than once, so why make every IAsyncOperation pay for it?

Next time, we’ll look at a case where you would want to await an IAsyncOperation more than once, and see what we can do to work around the C++/WinRT limitation.

Bonus chatter: There does exist a pre-existing library that supports multiple continuations: The Parallel Patterns Library concurrency::task object. The older C++/CX projection does not natively wrap the IAsyncOperation^, but the Parallel Patterns Library does have special knowledge of the C++/CX IAsyncOperation^, so you can wrap an IAsyncOperation^ inside a PPL task and co_await the task more than once.

So I guess you could say that somebody already wrote the wrapper for you. Unfortunately, that wrapper is quite bulky because the PPL library has so many features, most of which you probably aren’t using. You could say that while C++/WinRT tries to be minimalist, PPL tries to be maximalist. It’s easier to start small and grow and it is to start big and try to pare back. (And C++/WinRT generally delegates the “grow” part to the Windows Implementation Library, which adds additional features with headers like cppwinrt_helpers.h and cppwinrt_authoring.h.)

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.