Last time, we saw that if a C++/WinRT asynchronous operation is cancelled, the result is an hresult_. 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(¤t);
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_, which propagates back into C++/WinRT as hresult_.
And that solves the mystery of why some cancelled operations throw an hresult_ 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.
0 comments