不清楚如何将 winrt::get_cancellation_token 用于 IAsyncAction

Unclear how to use winrt::get_cancellation_token for IAsyncAction

我正在尝试在 C++/WinRT 中编写一个基于协程的后台线程,该线程在取消令牌的状态上循环,因为我需要对取消采取一些清理操作。

我正在尝试按照 MSDN (https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/concurrency#canceling-an-asychronous-operation-and-cancellation-callbacks) 上的文档进行操作,但示例代码的改编版无法编译,而且 cancellation_token_t 类型似乎不可调用。

void BackgroundThreadManager::Start()
{
    this->m_Thread = this->RunAsync();
}

void BackgroundThreadManager::Stop()
{
    if (this->m_Thread)
    {
        m_Thread.Cancel();
        m_Thread = nullptr;
    }
}

IAsyncAction BackgroundThreadManager::RunAsync()
{
    winrt::resume_background();
    auto token{ winrt::get_cancellation_token() };
    while (!token())
    {
        co_await this->DoSomethingAsync();
    }
    co_await this->DoSomeCleanupAsync();
}

不幸的是,这无法通过引用 "while (!token())" 行的 "error C2064: term does not evaluate to a function taking 0 arguments" 进行编译。

代码同意这一点,因为 get_cancellation_token_t 的定义(在 base.h 中)是

struct get_cancellation_token_t {};

我猜我从根本上做错了什么,或者 MSDN 文档已经过时了。有什么线索吗?谢谢!

您忘记在 get_cancellation_token() 表达式上 co_awaitco_await 提供库需要到达的钩子并获取可能被取消的 IAsyncAction 实例。顺便说一句,您还忘记了 co_await resume_background() 表达式。

此外,请注意协程也会在挂起点 (co_await) 自动取消,因此最好使用取消回调来确保您的取消逻辑不会被忽略。