What I know is that apartment_context is used to capture UI Thread and return to the UI Thread when it is in the background ThreadPool.
So, what is apartment_context actually in WinRT/C++? And how to use it properly and correctly? Then, is this object only able to capture UI Thread?
Finally, what are the advantages and disadvantages of using apartment_context compared to resume_foreground() and CoreDispatcher::RunAsync()?
Thanks
A
winrt::apartment_contextIn other words, it allows client code to store information about the current thread's apartment, switch to another apartment, and later return to it. It can be constructed on any thread, not just UI threads. However, since UI threads live in the special1 ASTA (Application Single-Threaded Apartment) and objects owned by those threads frequently have thread-affinity,
apartment_contextis primarily used with UI threads.The implementation wraps an
IContextCallbackinterface captured from a call toCoGetObjectContext. ItsContextCallbackmethodThis is fairly advanced with little to no official documentation available. Luckily, Raymond Chen has published two blog entries2,3 that cover this area in sufficient detail.
The interface of
apartment_context, by contrast, doesn't expose any of that complexity. It consists of a default constructor, and the three membersawait_ready(),await_suspend(), andawait_resume()that make it a coroutine awaiter4. Consequently, the only operations client code performs is to construct, andco_awaitit. Examples and explanations can be found at Programming with thread affinity in mind.As for advantages and disadvantages, it comes down to understanding what's going on. While
apartment_contextworks as advertised, it's important to keep in mind, that it captures the current context. As such, whether a coroutine works as desired becomes a liability of the caller. If (part of) a coroutine needs to execute on the UI thread, it's more robust to useresume_foreground, and more readable, too. The only downside here is that you need access to a dispatcher.Finally,
CoreDispatcher::RunAsyncultimately does the same thing. Except, it's part of the Windows Runtime, whereasresume_foreground()is part of the C++/WinRT library. I'm not aware of any functional differences.1 What is so special about the Application STA?
2 How do you get into a context via
IContextCallback::Contextallback?3 Using contexts to return to a COM apartment later
4 C++ Coroutines: Understanding operator co_await