Loading...
Loading...
C++/WinRT does not provide a wrapper that lets you await a Windows Runtime IAsyncOperation multiple times because C++ lacks a single standard async type to project onto. Languages like C#, JavaScript, and Python map IAsyncOperation to well-known standard types (Task, Promise, Future) that support multiple continuations; projections can reuse those implementations. C++ instead exposes IAsyncOperation directly and offers a minimal coroutine promise to avoid imposing the overhead of multi-continuat
Tech professionals working with Windows Runtime and C++ coroutines need reliable patterns for sharing async results without duplicating work. Understanding C++/WinRT choices affects API design, performance, and interoperability with other languages.
Dossier last updated: 2026-05-30 03:39:20
The article shows how to cache both success and failure results of an asynchronous Windows Runtime IAsyncOperation across multiple coroutines. Using a std::variant with std::monostate, winrt::Thing, and std::exception_ptr (or alternatively separate nullable members for result and exception), the code serializes access with a wil::unique_event so only one caller invokes GetThingWorkerAsync; the outcome—either the winrt::Thing or the captured exception—is stored and reused for subsequent callers. This prevents repeated retries on failure and guarantees consistent behavior for callers awaiting the same operation. The pattern is relevant for robust coroutine-based async APIs and resource sharing in Windows C++/WinRT code.
Windows developer Raymond Chen shows a simpler pattern for sharing the result of a single WinRT IAsyncOperation among multiple coroutines by serializing access with an auto-reset event and caching the result. The Widget example uses wil::unique_event and winrt::resume_on_signal to ensure only one coroutine runs the worker (GetThingWorkerAsync) while others await the signal; the result is stored in either std::optional<winrt::Thing> or a nullable winrt::Thing, depending on whether nullptr is a valid result. Exceptions from the worker leave the cache empty so subsequent callers can retry. Chen notes a future variant that will attempt the worker only once instead of retrying until success.
A C++/WinRT developer asked how to share a single Windows Runtime IAsyncOperation result across multiple coroutines so the work runs only once. The article contrasts the easy C# pattern (Task cached and awaited multiple times) with C++/WinRT, and analyzes a customer's implementation that used winrt::resume_on_signal, a manual-reset event, and a busy flag to coordinate callers. The author points out multiple bugs: data races (completion handler flips m_busy outside the mutex), lack of exception safety (worker construction can throw leaving m_busy stuck), and subtle timing races when the operation completes while another call is starting. The piece shows why naive synchronization is fragile and motivates safer patterns for sharing async results in C++/WinRT.
C++/WinRT does not provide a wrapper that lets you await a Windows Runtime IAsyncOperation multiple times because C++ lacks a single standard async type to project onto. Languages like C#, JavaScript, and Python map IAsyncOperation to well-known standard types (Task, Promise, Future) that support multiple continuations; projections can reuse those implementations. C++ instead exposes IAsyncOperation directly and offers a minimal coroutine promise to avoid imposing the overhead of multi-continuation support on every operation. The article notes workarounds: Microsoft’s Parallel Patterns Library (concurrency::task) can wrap IAsyncOperation and support multiple awaits but is heavyweight, while C++/WinRT prefers minimalism and delegates extras to helper libraries like the Windows Implementation Library.