我必须在C ++中实现异步HTTP GET,我们必须能够将应用程序提交到Windows 8商店。
我的问题如下:
我找到了一个合适的示例代码,它实现了一个HttpRequest类http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664
如果URI正确,此示例有效,但如果URI指向无效/非现有位置(例如:www.google22.com),则会引发异常。如果我可以捕获异常,那就没问题,但是我无法弄明白我应该如何或在哪里抓住它。
现在有些代码了。 这是对async,concurrency :: task方法的调用,该方法抛出异常:
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之前滑过所有内容。我在这些位置放置了断点(在简化/清理代码中):
执行顺序,使用断点进行测试:
打印的调试日志,按顺序: - 开始获取uri ... - App1.exe中0x75644B32的第一次机会异常:Microsoft C ++异常:Platform :: COMException ^在内存位置0x082FEEF0。 HRESULT:0x800C0005 - App1.exe中0x75644B32的第一次机会异常:Microsoft C ++异常:[rethrow]在内存位置0x00000000。 - App1.exe中0x75644B32的第一次机会异常:Microsoft C ++异常:Platform :: COMException ^在内存位置0x082FE670。 HRESULT:0x800C0005 - App1.exe中0x75644B32的第一次机会异常:Microsoft C ++异常:Platform :: COMException ^在内存位置0x082FDD88。 HRESULT:0x800C0005 - 未知异常
发生了什么事?
答案 0 :(得分:2)
在并发运行时中,任务执行期间发生的任何未处理的异常都会延迟以供以后观察。通过这种方式,您可以在链的末尾添加基于任务的延续并处理错误。
这样的事情:
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。
答案 1 :(得分:0)
这个相关的主题可能有一个线索: Visual C++ Unmanaged Code: Use /EHa or /EHsc for C++ exceptions?
如果要捕获所有异步异常,可以尝试设置配置属性 - &gt; C / C ++ - &gt;代码生成属性为&#34;是SEH例外(/ EHa)&#34;