Obsługa wyjątków, zadania asynchroniczne współbieżności WinRT C ++

Muszę zaimplementować asynchroniczny HTTP GET w C ++ i musimy być w stanie przesłać aplikację do Windows 8 Store.

Mój problem jest następujący:

Znalazłem odpowiedni przykładowy kod, który implementuje klasę HttpRequesthttp://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664

Ten przykład działa, jeśli identyfikator URI jest poprawny, ale zgłasza wyjątek, jeśli identyfikator URI wskazuje nieprawidłowe / nieistniejące miejsce (np .: www.google22.com). Byłoby dobrze, gdybym mógł złapać wyjątek, ale nie mogę zrozumieć, jak i gdzie powinienem go złapać.

Teraz trochę kodu. Jest to wywołanie metody async, concurrency :: task, która zgłasza wyjątek:

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

I to jest odpowiedni segment metody GetAsync (koniec metody):

// 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, stringCallback](tuple<HRESULT, wstring> resultTuple)
{
    // If the GET operation failed, throw an Exception.
    CheckHResult(std::get<0>(resultTuple));

    statusCode = stringCallback->GetStatusCode();
    reasonPhrase = stringCallback->GetReasonPhrase();

    return std::get<1>(resultTuple);
});

Linia CheckHResult zgłasza wyjątek, jest to kod:

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

Mam try-catch wokół wywołania GetAsync i mam także try-catch w .then kontynuacji lambda.

W odpowiedniej dokumentacji Microsoft (http://msdn.microsoft.com/en-us/library/windows/apps/hh780559.aspx ) stwierdza, że ​​wyjątki rzucone przez zadanie powinny być możliwe do przechwycenia w następnym zadaniu w łańcuchu, ale jakoś nie działa w moim przypadku. Dodatkowo, nawet próba przechwycenia całego połączenia nie wychwytuje wyjątku, tylko prześlizguje się przez wszystko ...

Czy ktoś miał ten problem? Myślę, że próbowałem wszystkiego, co podano w oficjalnych dokumentacjach, ale nadal pozwala to na wyjątek, który wpadł w szał i zawiesił aplikację. Czego mi brakuje?

EDYTOWAĆ:

Zmodyfikowałem kod, aby zrobić nic innego, jak obsługę wyjątków i nadal nie przechwytuje wyjątku zgłoszonego przez zadanie w .GetAsync

Oczyszczony kod:

try
{
  Windows::Foundation::Uri^ uri;
  uri = ref new Windows::Foundation::Uri( uri_string_to_fetch );

  concurrency::cancellation_token_source cancellationTokenSource = concurrency::cancellation_token_source();

  Web::HttpRequest httpRequest;
  OutputDebugString( L"Start to fetch the uri...\n" );
  httpRequest.GetAsync(uri, cancellationTokenSource.get_token())
    .then([](concurrency::task<std::wstring> response)
  {
    try {
      response.get();
    }
    catch( ... ) {
      OutputDebugString(L"unknown Exception");
    }
  })
  .then([](concurrency::task<void> t)
  {
    try {
      t.get();
      // .get() didn't throw, so we succeeded.
    }
    catch (Platform::Exception^ e) {
      // handle error
      OutputDebugString(L"Platform::Exception");
    }
    catch (...) {
      OutputDebugString(L"unknown Exception");
    }
  });
} 
catch (Platform::Exception^ ex) {
  OutputDebugString(L"Platform::Exception");
  errorCallback(-1);
} 
catch ( ... ) {
  OutputDebugString(L"unknown Exception");
  errorCallback(-2);
}

To nadal powoduje awarię z komunikatem wyjątku:Wyjątek pierwszej szansy pod adresem 0x75644B32 w App1.exe: wyjątek Microsoft C ++: Platform :: COMException ^ w lokalizacji pamięci 0x077EEC28. HRESULT: 0x800C0005

Dodatkowo, gdy umieściłem kilka punktów przerwania w kodzie, pokazuje, że wyjątek prześlizguje się przez wszystko, zanim zostanie wywołany pierwszy. Umieściłem punkty przerwania w tych lokalizacjach (w uproszczonym / wyczyszczonym kodzie):

przed wywołaniem GetAsyncdo GetAsync, doCheckHResult (std :: get <0> (resultTuple)); linia, która zgłasza wyjątekw każdą próbę i przypadek / blok catch

Kolejność wykonania, testowana z punktami przerwania:

przed wywołaniem GetAsync [OK]w GetAsync, wiersz, który rzuci wyjątek [OK]teraz aplikacja ulega awarii, prześlizguje się przez każdy try-catch, dalejteraz linia w pierwszym.następnie zostaje wywołany, w bloku tryinne wyjątki na poziomie aplikacji, które nie zostały przechwycone przez żaden blok catchteraz pierwszy.następnieblok catchdrugi. potem metodapróbować bloki nic więcej, drugi.następniecatch nawet nie łapie żadnego wyjątku

I drukowane dzienniki debugowania, w kolejności: - Zacznij pobierać uri ... - Wyjątek pierwszej szansy pod adresem 0x75644B32 w App1.exe: wyjątek Microsoft C ++: Platform :: COMException ^ w lokalizacji pamięci 0x082FEEF0. HRESULT: 0x800C0005 - Wyjątek pierwszej szansy przy 0x75644B32 w App1.exe: wyjątek Microsoft C ++: [rethrow] w lokalizacji pamięci 0x00000000. - Wyjątek pierwszej szansy pod adresem 0x75644B32 w App1.exe: wyjątek Microsoft C ++: Platform :: COMException ^ w lokalizacji pamięci 0x082FE670. HRESULT: 0x800C0005 - Wyjątek pierwszej szansy pod adresem 0x75644B32 w App1.exe: wyjątek Microsoft C ++: Platform :: COMException ^ w lokalizacji pamięci 0x082FDD88. HRESULT: 0x800C0005 - nieznany wyjątek

Co się dzieje??

questionAnswers(2)

yourAnswerToTheQuestion