create_task and return values

Sascha picture Sascha · Oct 6, 2012 · Viewed 17.2k times · Source

I need to call an Async method within a method I declared. The method should return a value. I'm trying to wrap calls to the Windows Store into an easy to use class. My method should look like this:

bool Purchase(enum_InAppOption optionToPurchase);

enum_InAppOption is an enum consisting of all In-App options to purchase. At some point I need to call RequestProductPurchaseAsync. The result of this call determines if the method should return trueor false. I'm new to c++/cx (or at least I have a long history between now and the last time I used c++), so maybe this is easier as I think.

The create_task looks like this:

create_task(CurrentAppSimulator::RequestProductPurchaseAsync(this->_LastProductId, false))

The options I considered / tried:

  1. returning the task would not abstract the store

  2. tried to call wait on the task. I've got the exception An invalid parameter was passed to a function that considers invalid parameters fatal.

  3. tried to use structured_task_group but it seems this does not allow for non void returning methods or I'm trying to provide a wrong interpretation. Compiler returns error C2064 (have googled but I can't get the point what to change)

  4. Using an array of tasks and when_all

Found the following code on http://msdn.microsoft.com/en-us/library/dd492427.aspx#when_all in the middle of the page:

array<task<void>, 3> tasks = 
{
    create_task([] { wcout << L"Hello from taskA." << endl; }),
    create_task([] { wcout << L"Hello from taskB." << endl; }),
    create_task([] { wcout << L"Hello from taskC." << endl; })
};

auto joinTask = when_all(begin(tasks), end(tasks));

// Print a message from the joining thread.
wcout << L"Hello from the joining thread." << endl;

// Wait for the tasks to finish.
joinTask.wait();

So I tried to translate it into the following code:

array<task<Platform::String^>,1> tasks = {
    create_task(CurrentAppSimulator::RequestProductPurchaseAsync(this->_LastProductId, false))
};

Even though I included the compiler throws C2065 ('array': undeclared identifier), C2275 ('Concurrency::task<_ReturnType>': illegal use of this type as an expression and some errors that seem to be errors following up on those two.

To sum up: How to make the method return after the async task has completed, so I can return a meaningful result based on the stuff going on asynchronously?

Answer

James McNellis picture James McNellis · Oct 7, 2012

How to make the method return after the async task has completed, so I can return a meaningful result based on the stuff going on asynchronously?

This doesn't make much sense: the "stuff" isn't asynchronous if you want to wait for it to complete before returning. That's the definition of synchronous.

When using C++/CX, you cannot wait on a not-yet-completed task on an STA. Any attempt to do so will result in an exception being thrown. If you are going to call Purchase() on an STA and if it starts an asynchronous operation, you cannot wait for that operation to complete before returning.

Instead, you can use .then to perform another operation when the asynchronous operation completes. If the continuation needs to be performed on the invoking thread, make sure to pass the use_current() continuation context to ensure that the continuation is executed in the correct context.