0

I have a c++ class object which performs some processing in the background of a uwp application.

Its process operation is called by Unity's "Update" method ~60fps through an UWP IAsyncOperation.

The class has a isBusy property which is set to true after calling the operation, in order to block it being called from unity again before it finishes.

Using task continuation, I would like to set this to false after the processing is complete and returned through the IAsyncOperation.


IAsyncOperation<ResultsWrapper^>^ SomeClass::SomeClassUpdateMethod() {

    return concurrency::create_async([this]() -> ResultsWrapper^
    { 
        // Block processing
        SomeClass::isBusy = true;

        // Process image and return to await
        LongRunningTask().then([this]() {
            return SomeClass::TaskResults; 
        }).then([this]() {
            isBusy = false;
        });
    });
}

concurrency::task<void> SomeClass::LongRunningTask(){

    auto results = ref new TaskResults();

    '''Work happens here'''

    SomeClass::TaskResults = results;
}


What I expect to happen is for the ResultWrapper object to be returned to the main thread of the calling application (Unity), then the isBusy flag of the object set to false by the task continuation.

What happens is:

Error C2338 incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below) \....\include\ppltasks.h
  • I know nothing about UWP, but, the first then returns something like task, so, shouldn't the second then take as input SomeClass::TaskResults? See here, section "Creating a chain of tasks": https://learn.microsoft.com/en-us/windows/uwp/threading-async/asynchronous-programming-in-cpp-universal-windows-platform-apps – CuriouslyRecurringThoughts Jul 24 '19 at 20:16
  • In my opinion the second `then` should be something like: `.then([this](TaskResults^ res)` – CuriouslyRecurringThoughts Jul 24 '19 at 22:37

1 Answers1

0

The reason this exception occurred is that you didn't return the ResultsWrapper^ type in the task chains.The second return you wrote means pass the value to the next chain to use instead of returning the value of the task.So you should write like the following code to return value correctly.

IAsyncOperation<ResultsWrapper^>^ SomeClass::SomeClassUpdateMethod() 
{

    return concurrency::create_async([this]() -> concurrency::task<ResultsWrapper^>
    { 

        SomeClass::isBusy = true;

        return LongRunningTask().then([this]() -> ResultsWrapper^
        {
            isBusy = false;
            return SomeClass::TaskResults; 
        });
    });
}

The code "return LongRunningTask().then(this ->ResultsWrapper^)" means convert the ResultsWrapper^ object to a task and return the task.

The return value of "LongRunningTask" method is task<void>,so you still need to return a task<void> value.

concurrency::task<void> SomeClass::LongRunningTask()
{
    return concurrency::create_task(
    [this]()
    {
        auto results = ref new TaskResults();
        '''Work happens here'''

        SomeClass::TaskResults = results;
    });

}
Faywang - MSFT
  • 5,798
  • 1
  • 5
  • 8