Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to consume WinRT IAsyncOperation* object in "native c++" environment

I have C/C++ SDK library which should be ported to Windows 8 Metro (WinRT). Library is mostly OS-independent, but it contains some modules which interact with hardware using OS-provided APIs.

While porting it to WinRT I've decided to try to use WRL instead of C++/CX as much as possible. So right now I can create and consume most of the required WinRT objects. But I've faced absolute obstacle while working with Async objects, provided by WinRT.

For example, I use following code to enumerate HW devices:

// create interface to "static" members of DeviceInformation class
ComPtr<IDeviceInformationStatics>   DeviceInformationStatics;
HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &DeviceInformationStatics);

ComPtr<IAsyncOperation<DeviceInformationCollection*>> operation;
hr = DeviceInformationStatics->FindAllAsyncDeviceClass( DeviceClass_All, &operation);

At this point I have valid IAsyncOperation pointer. I thought it can be used like that:

task<ComPtr<DeviceInformationCollection*>> tsk(operation);

but I failed, because task<> constructor which accepts IAsyncOperation is declared under "#if defined(__cplusplus_winrt)" in ppltasks.h, which, in turn, depends on /ZW compiler option.

How I'm supposed to use IAsyncOperation object in this case? Actually, I only need to wait for operation to be completed.

like image 452
Zakhar Avatar asked Sep 15 '25 12:09

Zakhar


2 Answers

Just in case someone else is looking for this in C++/WinRT:

    auto asyncOp = someFunctionReturningIAsyncOperation();

    asyncOp.Completed([](auto &&result, auto && status) {
        // do whatever with result and status
    });
like image 100
glennr Avatar answered Sep 18 '25 09:09

glennr


From my C++/CX experience, what you can do is you can construct an AsyncOperationCompletedHandler<DeviceInformationCollection*> object, initialize it with a member function in your class, and assign it to the Completed property of the IAsyncOperation.

In C++/CX, you just construct the AsyncOperationCompletedHandler<> object with two parameters - this from the calling class, and a pointer-to-member to a callback method. Like this:

MyAsyncOp->Completed = ref new AsyncOperationCompletedHandler<ResultType ^>(this, &MyClass::OnDone);

where OnDone is defined thus:

void MyClass::OnDone(IAsyncOperation<ResultType ^> ^AsOp, AsyncStatus s)
{
     ResultType ^Result = AsOp->GetResults();
}

I'm not sure how to call constructors in WRL. You figure this one out.

Also, the completion handler will be called on a random thread. If you need to pass something back to the UI thread, Dispatcher->RunAsync() is your friend. Most XAML classes have a Dispatcher member in them.

EDIT: now that I'm looking at samples, there seems to be a non-managed helper class called Callback that you construct around a this and a pointer-to-member. Look it up. Still not sure how to connect one to an IAsyncOperation though...

like image 35
Seva Alekseyev Avatar answered Sep 18 '25 10:09

Seva Alekseyev