gpt4 book ai didi

c++ - 异常处理、WinRT C++并发异步任务

转载 作者:搜寻专家 更新时间:2023-10-31 01:50:27 25 4
gpt4 key购买 nike

我必须在 C++ 中实现异步 HTTP 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,我在 .then continuation lambda 中也有一个 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);
}

这仍然让我崩溃并显示异常消息:App1.exe 中 0x75644B32 处的第一次机会异常:Microsoft C++ 异常:Platform::COMException ^ 在内存位置 0x077EEC28。 HRESULT:0x800C0005

此外,当我在代码中放置一些断点时,它显示异常会在第一个 .then 被调用之前跳过所有内容。我在这些位置放置了断点(在简化/清理代码中):

  • 在调用 GetAsync 之前
  • 进入 GetAsync,到 CheckHResult(std::get<0>(resultTuple)); 引发异常的行
  • 进入每一个 try and catch case/block

执行顺序,断点测试:

  1. 在 GetAsync 调用之前 [确定]
  2. 在 GetAsync 中,将抛出异常的行 [OK]
  3. 现在应用程序崩溃了,每次 try-catch 都漏掉了,继续
  4. 现在第一个 .then 中的行被调用,在它的 try block 中
  5. 另一个未被任何 catch block 捕获的应用级异常
  6. 现在是第一个 .then 的 catch block
  7. 第二个 .then 方法的 try block
  8. 仅此而已,第二个 .then 的 catch 甚至没有捕获到任何异常

以及打印的调试日志,按顺序: - 开始获取uri ... - App1.exe 中 0x75644B32 处的第一次异常:Microsoft C++ 异常:Platform::COMException ^ 在内存位置 0x082FEEF0。 HRESULT:0x800C0005 - App1.exe 中 0x75644B32 处的第一次异常:Microsoft C++ 异常:[重新抛出] 在内存位置 0x00000000。 - App1.exe 中 0x75644B32 处的第一次异常:Microsoft C++ 异常:Platform::COMException ^ 在内存位置 0x082FE670。 HRESULT:0x800C0005 - App1.exe 中 0x75644B32 处的第一次异常:Microsoft C++ 异常:Platform::COMException ^ 在内存位置 0x082FDD88。 HRESULT:0x800C0005 - 未知异常

发生了什么??

最佳答案

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

像这样:

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 会触发任务链中出现的任何异常(如果有的话)。有关更多详细信息,您可以阅读 Exception Handling in the Concurrency Runtime .

关于c++ - 异常处理、WinRT C++并发异步任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15119897/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com