Как отменить функцию асинхронного обратного вызова в C / WRL?

#c #windows-runtime #windows-10 #windows-store #wrl

#c #windows-среда выполнения #windows-10 #windows-store #wrl

Вопрос:

Я пишу код Windows 10 Store / WinRT, используя C / WRL, с которым я новичок. И мне любопытно узнать, как мне отменить давно ожидающую выполнения асинхронную операцию?

Лучший способ проиллюстрировать это на этом примере:

 #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?
}
  

РЕДАКТИРОВАТЬ: Когда я попытался добавить opAppLic->Cancel() , как было предложено в ответе ниже, это выдало мне следующую ошибку компилятора:

 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>          ]
  

Нужно ли мне QueryInterface это IAsyncInfo вместо этого или что?

EDIT2: Это то, что я получаю для типа opAppLic переменной:

введите описание изображения здесь

И нет, у него нет Cancel метода:

введите описание изображения здесь

Ответ №1:

IAsyncOperation<TResult> имеет Cancel() метод, унаследованный от IAsyncInfo .

Вы не можете отменить Completed сам обработчик. Она запускается по завершении асинхронной операции. Вместо этого вы должны отменить операцию, а затем Completed обработчик сообщает об окончательном статусе операции.

 #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();
  

Комментарии:

1. Извините. Для Cancel метода opAppLic нет. Я обновил свой первоначальный пост подробностями.

2. @c00000fd В документации MSDN, на которую я ссылался в своем ответе, указано иное: » IAsyncOperation<TResult> наследуется IAsyncInfo . Типы, которые реализуют IAsyncOperation<TResult> , также реализуют элементы интерфейса IAsyncInfo : Cancel метод , Close метод, ErrorCode свойство, Id property, Status property » Похоже, что настоящим виновником является RemoveIUnknown* возвращаемый ComPtr::operator->() . Я не знаю почему, но попробуйте использовать opAppLic.Get()->Cancel() вместо этого, поскольку Get() не использует RemoveIUnknown .

3. Спасибо. Я вижу документацию. Хотел бы я знать больше об этом материале, чтобы понять, почему Cancel метода там нет. Я обновил свой OP дополнительной информацией.

4. Эй, есть еще идеи по этому поводу?

5. @c00000fd: Извините, я не могу ответить на этот вопрос. Я не использую WRL.

Ответ №2:

Кто бы ни сталкивался с этим. Кажется, я понял. Реми Лебо был частично прав. Что мне нужно было сделать, так это получить IAsyncInfo via QueryInterface как таковой:

 ComPtr<IAsyncInfo> pAsyncInfo;
if(SUCCEEDED(opAppLic->QueryInterface(__uuidof(pAsyncInfo), amp;pAsyncInfo)) amp;amp;
    pAsyncInfo)
{
    if(SUCCEEDED(pAsyncInfo->Cancel()))
    {
        //Async op was now canceled
        //Also note that `onAppLicCompletedCallback` will be called
        //with `status` set to `Canceled`
    }
}
  

Комментарии:

1. ComPtr предоставляет более простой синтаксис для выполнения QueryInterface() с помощью As() метода. например. ComPtr<ABI::Windows::Foundation::IAsyncInfo> pAsyncInfo; opAppLic.As(amp;pAsyncInfo) . Для получения дополнительной информации см. — github.com/Microsoft/DirectXTK/wiki /…

2. Добавление к моему предыдущему комментарию ComPtr<ABI::Windows::Foundation::IAsyncInfo> pAsyncInfo; opAppLic.As(amp;pAsyncInfo) эквивалентно opAppLic->QueryInterface(__uuidof(pAsyncInfo), amp;pAsyncInfo))