July 7th, 2020

Cancelling a Windows Runtime asynchronous operation, part 5: C++/WinRT

Last time, we looked at how task cancellation is projected in C++/CX with PPL and co_await with IAsyncAction^ and IAsyncOperation^ objects. Our next investigation is 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);
}

Canceling the operation after a delay is slightly tricky because we need to pass the pickerOp as a parameter to a captureless lambda, rather than capturing it into the lambda. We discussed the reason for this some time ago.

The exception that comes out of awaiting for a canceled task is sometimes an hresult_canceled, and sometimes an hresult_illegal_method_call. The reason is that C++/WinRT defers to the IAsyncAction/IAsyncOperation to decide what exception to raise.¹

In other words, C++/WinRT just takes the ABI result and propagates it. It doesn’t try to impose its will upon the result.

You can see this in the await_resume for asynchronous operations:

template <typename Async>
struct await_adapter
{
    ...

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

Whatever exception comes out of Get­Results() is the exception that comes out of the co_await.

Next time, we’ll look at what happens if the IAsyncAction or IAsyncOperation was implemented by the C++/WinRT library itself.

Bonus chatter: This entire article is already obsolete. We’ll learn more about it when this series wraps up.

¹ Therefore, in principle, it could be utterly anything since it’s up to the ABI to generate the HRESULT that turns into an exception at the projection.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • cheong00

    While we’re on the topic with WinRT, I wonder if “removal of built-in WinRT support of .NET 5” will have impact on C++/WinRT or there will be another project to support it.

    https://github.com/dotnet/runtime/issues/37672

    • Max Strini

      C++/WinRT doesn’t use .NET at all – it’s a C++ library – so changes to .NET shouldn’t affect it.

      • cheong00

        Okay, I mixed it up.

        I saw C++/WinRT is for writing UWP and always thought it is a .NET technology.