How to catch exceptions which occur inside asynchronous methods? (Windows Store app, PPL)

May 20, 2013 at 7:02 AM
I am trying to catch exception from OnlineIdAuthenticator::AuthenticateUserAsync method, which occurs when there is no internet connection for example.

I've found some info about this topic, but it didn't really help me.

Here is the code which demonstrates the way that I tried to process errors:
auto auth = ref new OnlineIdAuthenticator ();
    auto request = ref new OnlineIdServiceTicketRequest ("wl.signin wl.basic wl.skydrive_update", "DELEGATION");
    auto request_vec = ref new Vector <OnlineIdServiceTicketRequest ^> ();
    request_vec->Append (request);

    create_task (auth->AuthenticateUserAsync (request_vec, CredentialPromptType::RetypeCredentials))
    .then ([] (UserIdentity ^ident)
    {
        try
        {
            auto ticket = ident->Tickets->GetAt (0);
            token = std::wstring (ticket->Value->Data ());
        }
        catch (const concurrency::task_canceled &)
        {
            int _break_point_here = 0;
        }
        catch (const std::exception &)
        {
            int _break_point_here = 0;
        }
        catch (Platform::Exception ^ex)
        {
            int _break_point_here = 0;
        }
    });
But no one from these catches doesn't work when AuthenticateUserAsync method fails.
Any help, please. What is the right way to catch exceptions from asynchronous method?
May 20, 2013 at 12:51 PM
Hi,

You can refer to "handling errors to task chain" section in below given url:
http://msdn.microsoft.com/en-us/library/windows/apps/hh780559.aspx

(In a task-based continuation, we call the member function task::get to get the results of the task. We still have to call task::get even if the operation was an IAsyncAction that produces no result because task::get also gets any exceptions that have been transported down to the task. If the input task is storing an exception, it is thrown at the call to task::get. If you don't call task::get, or don't use a task-based continuation at the end of the chain, or don't catch the exception type that was thrown, then an unobserved_task_exception is thrown when all references to the task have been deleted.)
May 20, 2013 at 4:07 PM
Yes, you need to pass the UserIdentity to the callback as a task. Use
.then([]task<UserIdentity^> idtask) { try { auto ident = idtask.get(); ... } catch ...  }
instead.
May 20, 2013 at 7:19 PM
Thank you, guys! Now it works.
auto auth = ref new OnlineIdAuthenticator ();
    auto request = ref new OnlineIdServiceTicketRequest ("wl.signin wl.basic wl.skydrive_update", "DELEGATION");
    auto request_vec = ref new Vector <OnlineIdServiceTicketRequest ^> ();
    request_vec->Append (request);

    task <UserIdentity ^> authenticationTask (auth->AuthenticateUserAsync (request_vec, CredentialPromptType::RetypeCredentials));
    
    authenticationTask.then ([] (task <UserIdentity ^> idtask)
    { 
        try 
        { 
            auto ident = idtask.get ();

            auto ticket = ident->Tickets->GetAt (0);
            token = std::wstring (ticket->Value->Data ());
        }

        catch (const concurrency::task_canceled &)
        {
            int _break_point_here = 0;
        }
        catch (const std::exception &)
        {
            int _break_point_here = 0;
        }
        catch (Platform::Exception ^ex)
        {
            std::wstring s = std::wstring (ex->Message->Data ());

            int _break_point_here = 0;
        }
    });
I am very appreciated for your help!