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é):
Ordre d’exécution, testé avec points d’arrêt:
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)”.