我所知道的是,apartment_context
用于捕获UI线程,并在后台ThreadPool中返回到UI线程。
那么,apartment_context
在WinRT/C++中究竟是什么呢?如何正确使用它?那么,这个对象只能捕获UI线程吗?
最后,与resume_foreground()
和CoreDispatcher::RunAsync()
相比,使用apartment_context
有哪些优点和缺点?
感谢
winrt::apartment_context
捕获协程中的线程上下文,以便稍后恢复。您实例化winrt::apartment_context值,然后稍后
co_await
它。
换句话说,它允许客户端代码存储关于当前线程的单元的信息,切换到另一个单元,然后返回到它。它可以在任何线程上构建,而不仅仅是UI线程。然而,由于UI线程位于特殊的1ASTA(应用程序单线程单元(中,并且这些线程所拥有的对象通常具有线程亲和性,因此apartment_context
主要用于UI线程。
该实现封装了从对CoGetObjectContext
的调用中捕获的IContextCallback
接口。其ContextCallback
方法
进入对象上下文,执行指定的函数,然后返回。
这是相当先进的,几乎没有官方文档可用。幸运的是,Raymond Chen已经发表了两篇博客文章2,3,详细介绍了这一领域。
相比之下,apartment_context
的接口并没有暴露出任何这种复杂性。它由一个默认构造函数和三个成员await_ready()
、await_suspend()
和await_resume()
组成,这三个成员使它成为协程awaiter4。因此,客户端代码执行的唯一操作就是构造和co_await
。可以在Programming中找到考虑到线程亲和性的示例和解释。
至于优点和缺点,归根结底是了解发生了什么。虽然apartment_context
如广告所示工作,但重要的是要记住,它捕捉到了当前的上下文。因此,协同程序是否按预期工作成为调用者的责任。如果协同程序(的一部分(需要在UI线程上执行,那么使用resume_foreground
更健壮,可读性也更高。这里唯一的缺点是您需要访问调度器。
最后,CoreDispatcher::RunAsync
最终也做了同样的事情。除了,它是Windows运行时的一部分,而resume_foreground()
是C++/WinRT库的一部分。我没有意识到任何功能上的差异。
1 应用程序STA有什么特别之处
2
如何通过IContextCallback::Contextallback
进入上下文
3 使用上下文稍后返回COM单元
4 C++推论:理解算子co-await