Gestion des exceptions, tâches asynchrones d’access simultané WinRT C ++

Je dois implémenter un HTTP GET asynchrone en C ++ et nous devons être en mesure de soumettre l’application au Windows 8 Store.

Mon problème est le suivant:

J’ai trouvé un exemple de code approprié qui implémente une classe HttpRequest http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664.

Cet exemple fonctionne si l’URI est correct mais lève une exception si l’URI pointe vers un emplacement non valide / non existant (comme: www.google22.com). Ce serait bien si je pouvais attraper l’exception, mais je ne peux pas comprendre comment ni où je devrais l’attraper.

Maintenant du code. C’est l’appel de la méthode async, concurrency :: task qui lève l’exception:

try { ... Web::HttpRequest httpRequest; httpRequest.GetAsync(uri, cancellationTokenSource.get_token()) .then( [] (concurrency::task response) { try { response.get(); } catch( ... ) { int i = 1; } return response; }) ... } catch ( ... ) { ... } 

Et voici le segment pertinent de la méthode GetAsync (la fin de la méthode):

 // Return a task that completes when the HTTP operation completes. // We pass the callback to the continuation because the lifetime of the // callback must exceed the operation to ensure that cancellation // works correctly. return completionTask.then([this, ssortingngCallback](tuple resultTuple) { // If the GET operation failed, throw an Exception. CheckHResult(std::get(resultTuple)); statusCode = ssortingngCallback->GetStatusCode(); reasonPhrase = ssortingngCallback->GetReasonPhrase(); return std::get(resultTuple); }); 

La ligne CheckHResult lève l’exception, c’est le code:

 inline void CheckHResult(HRESULT hResult) { if (hResult == E_ABORT) { concurrency::cancel_current_task(); } else if (FAILED(hResult)) { throw Platform::Exception::CreateException(hResult); } } 

J’ai un try-catch autour de l’appel GetAsync et j’ai également un try-catch dans la suite .then lambda.

Dans la documentation Microsoft pertinente ( http://msdn.microsoft.com/en-us/library/windows/apps/hh780559.aspx ), il est indiqué que les exceptions levées par une tâche doivent pouvoir être capturées dans la tâche suivante de la chaîne, mais ça ne marche pas dans mon cas. De plus, même les tentatives d’appel de l’appel ne font pas exception à la règle.

Quelqu’un a eu ce problème? Je pense avoir tout essayé dans les documentations officielles, mais cela laisse quand même l’exception devenir fou et écraser l’application. Qu’est-ce qui me manque?

MODIFIER:

J’ai modifié le code pour qu’il ne fasse rien d’autre que la gestion des exceptions et qu’il ne capture toujours pas l’exception levée par la tâche dans .GetAsync

Code nettoyé:

 try { Windows::Foundation::Uri^ uri; uri = ref new Windows::Foundation::Uri( uri_ssortingng_to_fetch ); concurrency::cancellation_token_source cancellationTokenSource = concurrency::cancellation_token_source(); Web::HttpRequest httpRequest; OutputDebugSsortingng( L"Start to fetch the uri...\n" ); httpRequest.GetAsync(uri, cancellationTokenSource.get_token()) .then([](concurrency::task response) { try { response.get(); } catch( ... ) { OutputDebugSsortingng(L"unknown Exception"); } }) .then([](concurrency::task t) { try { t.get(); // .get() didn't throw, so we succeeded. } catch (Platform::Exception^ e) { // handle error OutputDebugSsortingng(L"Platform::Exception"); } catch (...) { OutputDebugSsortingng(L"unknown Exception"); } }); } catch (Platform::Exception^ ex) { OutputDebugSsortingng(L"Platform::Exception"); errorCallback(-1); } catch ( ... ) { OutputDebugSsortingng(L"unknown Exception"); errorCallback(-2); } 

Cela me donne toujours un blocage avec le message d’exception: Exception de première chance à 0x75644B32 dans App1.exe: exception Microsoft C ++: Platform :: COMException ^ à l’emplacement de mémoire 0x077EEC28. HRESULT: 0x800C0005

De plus, lorsque je mets des points d’arrêt dans le code, cela indique que l’exception passe au premier plan avant que le premier .then soit appelé. J’ai mis des points d’arrêt à ces emplacements (dans le code simplifié / nettoyé):

  • avant l’appel GetAsync
  • dans GetAsync, dans CheckHResult (std :: get (resultTuple)); ligne qui lève l’exception
  • dans chaque essai et attraper cas / bloc

Ordre d’exécution, testé avec points d’arrêt:

  1. avant l’appel GetAsync [OK]
  2. dans GetAsync, la ligne qui lève l’exception [OK]
  3. maintenant l’application se bloque, glisse à travers toutes les tentatives , continue
  4. maintenant la ligne dans le premier .then est appelée, dans son bloc try
  5. une autre exception de niveau d’application non interceptée par un bloc d’interception
  6. maintenant le bloc de capture du premier .then
  7. deuxième bloc try de la méthode .then
  8. et rien de plus, la capture du second .then ne prend même pas une exception

Et les journaux de débogage imprimés, dans l’ordre: – Commencez par extraire l’URI … – Exception de première chance à 0x75644B32 dans App1.exe: exception Microsoft C ++: Platform :: COMException ^ à l’emplacement de la mémoire 0x082FEEF0. HRESULT: 0x800C0005 – Exception de première chance à 0x75644B32 dans App1.exe: exception Microsoft C ++: [Rethrow] à l’emplacement de mémoire 0x00000000. – Exception de première chance à 0x75644B32 dans App1.exe: exception Microsoft C ++: Platform :: COMException ^ à l’emplacement de mémoire 0x082FE670. HRESULT: 0x800C0005 – Exception de première chance à 0x75644B32 dans App1.exe: exception Microsoft C ++: Platform :: COMException ^ à l’emplacement de mémoire 0x082FDD88. HRESULT: 0x800C0005 – Exception inconnue

Qu’est-ce qui se passe??

Dans le runtime de concurrence, toute exception non gérée qui se produit pendant l’exécution d’une tâche est différée pour une observation ultérieure. De cette manière, vous pouvez append une continuation basée sur une tâche à la fin de la chaîne et y gérer les erreurs.

Quelque chose comme ça:

 httpRequest.GetAsync(uri, cancellationTokenSource.get_token()) .then([](concurrency::task response) { try { response.get(); } catch( ... ) { int i = 1; } return response; }) .then([](concurrency::task t) { try { t.get(); // .get() didn't throw, so we succeeded. } catch (Platform::Exception::CreateException^ e) { // handle error } }); 

L’appel à .get déclenche toutes les exceptions qui ont été déclenchées dans la chaîne de tâches (le cas échéant). Pour plus de détails, vous pouvez lire le traitement des exceptions dans le runtime d’access simultané .

Ce thread associé peut avoir un indice: Code non géré Visual C ++: Utilisez / EHa ou / EHsc pour les exceptions C ++?

Si vous voulez intercepter toutes les exceptions asynchrones, vous pouvez essayer de définir votre propriété de configuration Propriétés -> C / C ++ -> Code à “Oui avec les exceptions SEH (/ EHa)”.