[Windows翻译]取消一个Windows Runtime异步操作,第5部分:C++/WinRT。

258 阅读1分钟

原文地址:devblogs.microsoft.com/oldnewthing…

原文作者:devblogs.microsoft.com/oldnewthing…

发布时间:2020年7月7日

上一次,我们研究了在C++/CX中如何用PPL和co_await与IAsyncAction^和IAsyncOperation^对象投射任务取消。我们下一次研究的是C++/WinRT。

FileOpenPicker openPicker;
openPicker.FileTypeFilter().Append(L".txt");
auto pickerOp = openPicker.PickSingleFileAsync();
([](auto op) -> fire_and_forget { co_await resume_after(3s); op.Cancel(); })(pickerOp);

StorageFile file{ nullptr };
try
{
    file = co_await pickerOp;
}
catch (hresult_canceled const&)
{
    file = nullptr;
}
catch (hresult_illegal_method_call const&)
{
    file = nullptr;
}

if (file != nullptr)
{
    DoSomething(file);
}

在延迟后取消操作稍微有点棘手,因为我们需要把pickerOp作为参数传递给一个无捕获的lambda,而不是把它捕获到lambda中。前段时间我们讨论过其中的原因。

等待取消的任务所产生的异常有时是一个hresult_canceled,有时是一个hresult_illegal_method_call。原因是,C++/WinRT服从于IAsyncAction/IAsyncOperation来决定引发什么异常¹

换句话说,C++/WinRT只是接受ABI结果并传播它。它并不试图将自己的意志强加在结果上。

你可以在异步操作的 await_resume 中看到这一点。

template <typename Async>
struct await_adapter
{
    ...

    auto await_resume() const
    {
        return async.GetResults();
    }
};

不管GetResults()中出现什么异常,都是co_await中出现的异常。

下一次,我们将看看如果IAsyncAction或IAsyncOperation是由C++/WinRT库本身实现的会发生什么。

额外的唠叨。这整篇文章已经过时了 当这个系列结束时,我们将了解更多的信息。

¹因此,原则上,它完全可以是任何东西,因为它是由ABI来生成在投影处变成异常的HRESULT。


通过www.DeepL.com/Translator (免费版)翻译