Search code examples
windows-runtimewinrt-async

How to wait for an IAsyncAction?


In Windows Store Apps, C++(C# is similar though), doing something like

IAsyncAction^ Action = CurrentAppSimulator::ReloadSimulatorAsync(proxyFile);
create_task( Action ).then([this]()
{
}.wait();

results in an unhandled exception. Usually it's

Microsoft C++ exception: Concurrency::invalid_operation at memory location 0x0531eb58

And I kind of need for that action to finish to get my In App Purchase information before trying to use it. The weird thing here is that anything else besides IAsyncAction waits just fine. IAsyncOperation and IAsyncOperationWithProgress worked just fine, but this ? Exception and then crash.

To be honest, I have no idea what's the difference between an IAsyncOperation and an IAsyncAction, they seem similar to me.

UPDATE :

By analyzing this page http://msdn.microsoft.com/en-us/library/vstudio/hh750082.aspx you can figure out that IAsyncAction is just an IAsyncOperation without a return type. But, you can then see that most IAsyncAction-s are waitable. The real problem though is that certain Windows functions just want to execute on a particular thread (for some reason). ReloadSimulatorAsync is one such fine example.

Using code like this :

void WaitForAsync( IAsyncAction ^A )
{   
    while(A->Status == AsyncStatus::Started)
    {
        std::chrono::milliseconds milis( 1 );
        std::this_thread::sleep_for( milis );
    }   
    AsyncStatus S = A->Status;  
}

results in an infinite loop. If called upon other functions it actually works. The problem here is why does a task need to be executed on a particular thread if everything is Async ? Instead of Async it should be RunOn(Main/UI)Thread or similar.

SOLVED, see answer;


Solution

  • This is the magical fix that gets the job done :

    void WaitForAsync( IAsyncAction ^A )
    {   
        while(A->Status == Windows::Foundation::AsyncStatus::Started)
        {   
            CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);                     
        }
    
        Windows::Foundation::AsyncStatus S = A->Status; 
    }