原文地址:devblogs.microsoft.com/oldnewthing…
原文作者:devblogs.microsoft.com/oldnewthing…
发布时间:2020年7月9日
上一次,我们看到,如果一个C++/WinRT异步操作被取消,结果是一个hresult_canceled。今天,我们就来看看另一个异步操作的实现库。Windows Runtime模板库(WRL)。
WRL现在已经有点过时了,但在它的全盛时期,它是大家用来创建Windows Runtime对象和异步操作的东西。
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;
}
}
...
}
};
CheckValidStateForResultsCall方法的作用是:验证操作是否处于正确的状态,以便调用GetResults()。在操作已被取消的情况下,我们会失败第一项测试(会传播任何显式错误代码),但会使其进入第二部分。这是一个单结果操作¹,被取消的操作是不完整的,所以它返回E_ILLEGAL_METHOD_CALL,它以hresult_illegal_method_call的形式传播回C++/WinRT中。
这就解决了为什么一些被取消的操作会抛出一个hresult_illegal_method_call异常的谜团。我们花了一个星期的时间,但我们终于做到了。取消操作的传播是操作和等待者之间的微妙舞蹈,很容易被绊倒。
¹几乎所有的Windows Runtime异步操作都是单结果的。还有一种很少见的变体叫做多结果异步操作,它让你在操作完成之前就调用GetResults,它给你结果-so-far。我不知道有什么操作可以这样做,但代码支持。