July 9th, 2020

Cancelling a Windows Runtime asynchronous operation, part 7: WRL-generated asynchronous operations

Last time, we saw that if a C++/WinRT asynchronous operation is cancelled, the result is an hresult_canceled. Today, we’ll look at another implementation library for asynchronous operations: The Windows Runtime Template Library (WRL).

WRL is a bit out of fashion nowadays, but back in its heyday, it was the stuff everybody used for creating Windows Runtime objects and asynchronous operations.

class AsyncBase< ... > : ...
{
    inline HRESULT CheckValidStateForResultsCall()
    {
        Details::AsyncStatusInternal current = Details::_Undefined;
        CurrentStatus(&current);

        if (current == Details::_Error)
        {
            ...
        }

        if (resultType == SingleResult)
        {
            if (current != Details::_Completed)
            {
                ::RoOriginateError(E_ILLEGAL_METHOD_CALL, nullptr);
                return E_ILLEGAL_METHOD_CALL;
            }
        }
        ...
    }
};

The Check­Valid­State­For­Results­Call method does what is says: It validates that the operation is in a correct state for a call to Get­Results(). In the case where the operation has been canceled, we fail the first test (which propagates any explicit error code), but make it into the second part. This is a single-result operation¹ and a cancelled operation is not complete, so it returns E_ILLEGAL_METHOD_CALL, which propagates back into C++/WinRT as hresult_illegal_method_call.

And that solves the mystery of why some cancelled operations throw an hresult_illegal_method_call exception. It took us a week to get here, but we finally made it. The propagation of cancellation is a delicate dance between the the operation and the awaiter, and it’s easy to stumble.

¹ Nearly all Windows Runtime asynchronous operations are single-result. There’s another rarely-seen variant called the multiple-result asynchronous operation, which lets you call Get­Results before the operation has completed, and it gives you the result-so-far. I am not aware of any operations that do this, but the code supports.

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.

0 comments

Discussion are closed.