How to cancel asynchronous callback function in C+

2019-06-01 03:48发布

I'm writing Windows 10 Store / WinRT code using C++/WRL which I'm new to. And I'm curious to know how do I cancel long-pending asynchronous operation?

The best way to illustrate it is with this example:

#include <Windows.Services.Store.h>
#include <wrl.h>

auto onAppLicCompletedCallback = Callback<Implements<RuntimeClassFlags<ClassicCom>, IAsyncOperationCompletedHandler<StoreAppLicense*>, FtmBase>>(
    [](IAsyncOperation<StoreAppLicense*>* operation, AsyncStatus status)
{
    //Asynchronous operation is done
    return S_OK;
});

//'opAppLic' is defined as:
// ComPtr<IAsyncOperation<StoreAppLicense*>> opAppLic;
// ...

//Begin asynchronous operation
HRESULT hr = opAppLic->put_Completed(onAppLicCompletedCallback.Get());
if (SUCCEEDED(hr))
{
    //Keep going ...

    //Say, at some point here I need to cancel 'onAppLicCompletedCallback'
    //but how do I do it?
}

EDIT: When I tried to add opAppLic->Cancel() as was suggested in the answer below, it gave me the following compiler error:

1>file-name.cpp(597): error C2039: 'Cancel' : is not a member of 'Microsoft::WRL::Details::RemoveIUnknownBase<T>'
1>          with
1>          [
1>              T=ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Services::Store::StoreAppLicense*>
1>          ]

Do I need to QueryInterface that IAsyncInfo instead, or what?

EDIT2: This is what I'm getting for the type of opAppLic variable:

enter image description here

And no, it doesn't have the Cancel method:

enter image description here

2条回答
干净又极端
2楼-- · 2019-06-01 04:39

IAsyncOperation<TResult> has a Cancel() method inherited from IAsyncInfo.

You cannot cancel the Completed handler itself. It is fired when the async operation is finished. You have to cancel the operation instead, and then the Completed handler reports the final status of the operation.

#include <Windows.Services.Store.h>
#include <wrl.h>

auto onAppLicCompletedCallback = Callback<Implements<RuntimeClassFlags<ClassicCom>, IAsyncOperationCompletedHandler<StoreAppLicense*>, FtmBase>>(
    [](IAsyncOperation<StoreAppLicense*>* operation, AsyncStatus status)
{
    //Asynchronous operation is done
    if (status == completed)
    {
        // use results from operation->GetResults() as needed...
    }
    return S_OK;
});

ComPtr<IAsyncOperation<StoreAppLicense*>> opAppLic;
// Begin asynchronous operation that assigns opAppLic...

opAppLic->put_Completed(onAppLicCompletedCallback.Get());

//Keep going ...

//Say, at some point here I need to cancel the operation...
opAppLic->Cancel();
查看更多
淡お忘
3楼-- · 2019-06-01 04:41

Whoever also runs into this. I think I got it. Remy Lebeau was partially correct. What I needed to do was to obtain IAsyncInfo via QueryInterface as such:

ComPtr<IAsyncInfo> pAsyncInfo;
if(SUCCEEDED(opAppLic->QueryInterface(__uuidof(pAsyncInfo), &pAsyncInfo)) &&
    pAsyncInfo)
{
    if(SUCCEEDED(pAsyncInfo->Cancel()))
    {
        //Async op was now canceled
        //Also note that `onAppLicCompletedCallback` will be called
        //with `status` set to `Canceled`
    }
}
查看更多
登录 后发表回答