异常处理,WinRT的C ++并行异步任务(Exception handling, WinRT C+

2019-07-20 16:18发布

我要实现一个异步HTTP在C ++ GET,我们必须能够将应用程序提交到Windows 8商店。

我的问题是这样的:

我发现它实现的HttpRequest类合适的示例代码http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664

这个例子工作,如果URI是正确的,但如果抛出URI指向一个例外,一个无效的/不存在的地方(如:www.google22.com)。 这将是很好,如果我能捕捉到了异常,但我无法弄清楚如何或我应该在哪里抓住它。

现在一些代码。 这是在调用异步,并行任务::根据其抛出异常的方法:

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 ( ... ) {
...
}

这就是GetAsync方法(该方法的结束时)的相关段:

// 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);
});

该CheckHResult行抛出异常,它的代码:

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

我周围有GetAsync调用一个try-catch我也有一个try-catch中。然后继续拉姆达。

在相关Microsoft文档( http://msdn.microsoft.com/en-us/library/windows/apps/hh780559.aspx )它指出由任务引发的异常应在链,但不知下一个任务开捕它不会在我的情况下工作。 整个待命,另外甚至没有在try-catch捕获该异常,它只是通过一切滑...

任何人有这个问题? 我想我已经尝试在官方单证陈述的一切,但它仍然可以让异常发狂和崩溃的应用程序。 我怎么错过?

编辑:

我已经修改了代码,别的什么也不要做异常处理,它仍然不赶在.GetAsync任务抛出的异常

清理后的代码:

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);
}

这仍然给了我异常消息崩溃: 内存位置0x077EEC28平台::收到COMException ^:第一次机会异常在0x75644B32在App1.exe:微软C ++异常。 HRESULT:0x800C0005

此外,当我把一些断点在代码中充分显示了例外通过一切滑倒第一。然后将被称为前。 我已经把断点在这些位置(在简化/清理代码):

  • 在GetAsync调用之前
  • 入GetAsync到CheckHResult(标准::得到<0>(resultTuple)); 线,其引发该异常
  • 到每一个尝试和catch情况/块

执行顺序,带有断点测试:

  1. 在GetAsync调用之前[OK]
  2. 在GetAsync,这将引发异常的行[OK]
  3. 现在应用程序崩溃,滑过每一个的try-catch,继续
  4. 现在第一。然后行被调用,在它的试块
  5. 另一个应用程序级的异常,没有任何catch块逮住
  6. 现在第一。那么的catch块
  7. 第二。那么方法的try
  8. 仅此而已,旗下第二。后来赶上甚至不捕捉任何异常

和印刷调试日志,以便: - 开始,以获取URI ... - 在0x75644B32在App1.exe第一次机会异常:微软C ++异常:平台::收到COMException ^内存位置0x082FEEF0。 HRESULT:0x800C0005 - 在0x75644B32在App1.exe第一次机会异常:微软C ++异常:[重新抛出]在内存位置00000000。 - 在0x75644B32在App1.exe第一次机会异常:微软C ++异常:平台::收到COMException ^内存位置0x082FE670。 HRESULT:0x800C0005 - 在0x75644B32在App1.exe第一次机会异常:微软C ++异常:平台::收到COMException ^内存位置0x082FDD88。 HRESULT:0x800C0005 - 未知异常

怎么了??

Answer 1:

在并发运行时任务的执行过程中发生的任何未处理的异常被推迟到以后观察。 通过这种方式,你可以在链的末端添加一个基于任务延续和处理错误那里。

事情是这样的:

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

要将呼叫.get触发任务链(如果有的话)中提出的任何异常。 欲了解更多详细信息,你可以阅读在并发运行时异常处理 。



Answer 2:

该相关线程可以有一个线索: VISUAL C ++非托管代码:使用/ EHA或/ EHSC用于C ++异常?

如果你想抓住所有的非同步异常,你可以尝试在配置属性 - > C / C ++设置 - >代码生成属性设置为“是与SEH异常(/ EHA)”



文章来源: Exception handling, WinRT C++ concurrency async tasks