Creating an already-completed asynchonous activity in C++/WinRT, part 1

Raymond Chen

When working with asynchronous code, you may need to create an asynchronous activity that has already completed, because you already know the answer. For example, you may be implementing a method whose signature is

IAsyncOperation<int> ComputeAsync();

but you already have the result and don’t need to compute it. How can you return an IAsyncOperation<int> that represents the already-computed result?

C# has Task.FromResult() and Task.CompletedTask. JavaScript has Promise.resolve(). The Parallel Patterns Library (PPL) has task_from_result(). What about C++/WinRT?

The simplest way is to just co_return the result into a coroutine.

winrt::Windows::Foundation::IAsyncOperation<int>
    ComputeAsync()
{
    co_return 42;
}

Similarly, C# has Task.FromException(), JavaScript has Promise.reject(), and PPL has task_from_exception(). The simple C++/WinRT version is to throw the exception from the coroutine.

But wait, this doesn’t do what you think:

winrt::Windows::Foundation::IAsyncOperation<int>
    ComputeAsync()
{
    throw winrt::hresult_access_denied();
}

There is no co_await or co_return statement in the function body, so this is not a coroutine: Instead of returning a failed coroutine, this function fails to return a coroutine! When you call it, it throws an exception.

We’ll look at ways of making this a coroutine next time.

2 comments

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


Newest
Newest
Popular
Oldest
  • Jacob Manaker 0

    Perhaps the following?

    
    winrt::Windows::Foundation::IAsyncOperation<int> ComputeAsync(void) noexcept
    {
        co_await std::suspend_never{};
        throw winrt::hresult_access_denied();
    }
    
    • LB 0

      I’m not sure how IAsyncOperation’s promise type handles the situation where dynamic allocation of the coroutine frame fails, that usually results in throwing std::bad_alloc, so you can’t mark the function as noexcept in that case. If it has some non-throwing way of handling that case though then I suppose the noexcept is fine. It’s a shame there’s no way for a promise type to detect whether the function signature contains noexcept or not.

Feedback usabilla icon