locked
Some IAsync-s aren't waitable, why ? and how to determine that ?

    Question

  • In Windows 8, there's only async operations. While most of them are waitable, some are not and are throwing exceptions/crashes. One that I found is :

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

    resulting in:

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

    Now, the thing is that I even tried to wait for it with code like :

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

    And it results in an infinite loop.

    This basically means that the so called "asynchronous" operation is not asynchronous

    at all and it kind of wants to be executed on the current thread for some

    reason at a later time. So how do I verify if an asynchronous call wants

    to execute on the current thread ? and why can't I tell it to execute on

    a separate thread so I can wait for it on the current thread ?


    http://www.facebook.com/relativegames



    Thursday, November 14, 2013 12:04 PM

Answers

  • This is the magical fix for unwaitable tasks.

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



    http://www.facebook.com/relativegames



    Sunday, November 17, 2013 4:54 PM

All replies

  • To call it asynchronously put your followup code in the completion handler in the then clause. When the async task finishes the completion handler will run.

    The problem in the first snippet is that you are making it synchronous and blocking the dispatcher thread with your "wait". This is not allowed. Calling wait on the dispatcher thread will fail with the error you mention.

    The second loop is uglier. Even if it exits it will lock up the UI waiting for the task to finish. I suspect it doesn't exit because it blocks the task from completing back to the dispatcher thread.

    The solution to both is the same: let async be async. Put the response in the completion handler. Do not try to squeeze the async out of the function and force it to run synchronously.

    Thursday, November 14, 2013 2:03 PM
    Owner
  • Dispatcher thread ? As I said above, some functions run on other threads by default, others want to execute on the current thread, why is that ? Asynchronous by definition means that it should run indifferent to the current thread after it is started, does it not ? Ergo, if it doesn't execute on other threads, it is actually synchronous. Why are some operations tied to this "Dispatcher thread" and others not ? How can I detect this dependency ? this is my question, stay on the subject please.

    http://www.facebook.com/relativegames


    Thursday, November 14, 2013 3:17 PM
  • This is the magical fix for unwaitable tasks.

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



    http://www.facebook.com/relativegames



    Sunday, November 17, 2013 4:54 PM