异常处理,WinRT C ++并发异步任务

编程入门 行业动态 更新时间:2024-10-07 06:40:12
本文介绍了异常处理,WinRT C ++并发异步任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

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

我的问题如下:

我找到了一个合适的示例代码,它实现了一个HttpRequest类 code.msdn.microsoft/windowsapps/HttpClient-sample-55700664

此示例工作如果URI是正确的,但如果URI指向无效/不存在的地方(例如:www.google22),则会抛出异常。这将是罚款,如果我可以捕获异常,但我不能弄清楚如何或在哪里应该捕获它。

现在一些代码。 这是调用async,concurrency ::任务的方法抛出异常:

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

这是GetAsync方法的相关段(方法的结尾):

//返回在HTTP操作完成时完成的任务。 //我们将回调传递给延续,因为 //回调的生命周期必须超过操作,以确保取消 //正常工作。 return completionTask.then([this,stringCallback](tuple< HRESULT,wstring> resultTuple) { //如果GET操作失败,抛出一个异常 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); } }

我有一个try-catch GetAsync调用和我还在.then继续lambda中有一个try-catch。

在相关的Microsoft文档( msdn.microsoft/en-us/library/windows/apps/hh780559.aspx )it states任务抛出的异常应该可以在链中的下一个任务中捕获,但不知何故,它在我的情况下不工作。此外,即使整个调用的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开始获取uri ... \\\); httpRequest.GetAsync(uri,cancellationTokenSource.get_token()) .then([](concurrency :: task< std :: wstring> response) { try { response.get(); } catch(...){ OutputDebugString(Lunknown Exception); } }) .then([](concurrency :: task< void> t) { try { t.get(); // .get 't throw,所以我们成功了。} catch(Platform :: Exception ^ e){ // handle error OutputDebugString(LPlatform :: Exception); } catch(...){ OutputDebugString(Lunknown Exception); } }); } catch(Platform :: Exception ^ ex){ OutputDebugString(LPlatform :: Exception); errorCallback(-1); } catch(...){ OutputDebugString(Lunknown Exception); errorCallback(-2); }

这仍然会导致异常消息崩溃:机会异常在0x75644B32在App1.exe:Microsoft C ++异常:Platform :: COMException ^在内存位置0x077EEC28。 HRESULT:0x800C0005

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

  • 在GetAsync调用之前
  • 插入到GetAsync,到 CheckHResult(std :: get< 0>(resultTuple)); 行,将抛出异常
  • try&catch case / block

执行顺序,使用断点测试:

<在GetAsync调用[OK]
  • 之前,在$ GetAsync中调用
  • 现在应用崩溃了,每次尝试try ,继续
  • 现在第一个 .then
  • 另一个应用程式层级例外未被任何catch块捕获
  • 现在是第一个<
  • 第二个
  • / em>的catch甚至不会捕获任何异常

    和打印的调试日志,顺序: - 开始获取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 - 未知异常

    发生了什么?

    解决方案

    在并发运行时,在任务执行期间发生的任何未处理的异常将被推迟以供以后观察。这样,你可以在链接末尾添加一个基于任务的延续,并处理错误。

    这样的东西:

    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()没有抛出,所以我们成功了} catch(Platform :: Exception :: CreateException ^ e){ // handle error } });

    调用 .get 会触发任何异常在任务链(如果有)中提出。 有关详细信息,请参阅并发运行时中的异常处理。

    I have to implement an async HTTP GET in C++ and we have to be able to submit the app to the Windows 8 Store.

    My problem is the following:

    I've found a suitable Sample code which implements an HttpRequest class code.msdn.microsoft/windowsapps/HttpClient-sample-55700664

    This example works if the URI is correct but throws an exception if the URI points to an invalid / non existing place (like: www.google22). This would be fine if I could catch the exception but I cannot figure it out how or where should I catch it.

    Now some code. This is the call to the async, concurrency::task based method which throws the exception:

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

    And this is the relevant segment of the GetAsync method (the end of the method):

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

    The CheckHResult line throws the exception, it's code:

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

    I have a try-catch around the GetAsync call and I also have a try-catch in the .then continuation lambda.

    In the relevant Microsoft documentation ( msdn.microsoft/en-us/library/windows/apps/hh780559.aspx ) it states that exceptions thrown by a task should be catchable in the next task in the chain but somehow it doesn't work in my case. Additionally not even the try-catch around the whole call catches the exception, it just slips through everything...

    Anyone had this problem? I think I've tried everything stated in the official documentations but it still lets the exception go berserk and crash the app. What do I miss?

    EDIT:

    I've modified the code to do nothing else but exception handling and it still doesn't catch the exception thrown by the task in .GetAsync

    Cleaned-up code:

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

    This still gives me a crash with the exception message: First-chance exception at 0x75644B32 in App1.exe: Microsoft C++ exception: Platform::COMException ^ at memory location 0x077EEC28. HRESULT:0x800C0005

    Additionally when I put some breakpoints in the code it shows that the exception slips through everything before the first .then would be called. I've put breakpoints in these locations (in the simplified / cleaned up code):

    • before the GetAsync call
    • into the GetAsync, to the CheckHResult(std::get<0>(resultTuple)); line which throws the exception
    • into every try and catch case / block

    Order of execution, tested with breakpoints:

  • before the GetAsync call [OK]
  • in the GetAsync, the line which will throw the exception [OK]
  • now the app crashes, slips through every try-catch, continue
  • now the line in the first .then gets called, in it's try block
  • another app level exceptions not catched by any catch block
  • now the first .then's catch block
  • second .then method's try block
  • and nothing more, the second .then's catch doesn't even catch any exception
  • And the printed debug logs, in order: - Start to fetch the uri... - First-chance exception at 0x75644B32 in App1.exe: Microsoft C++ exception: Platform::COMException ^ at memory location 0x082FEEF0. HRESULT:0x800C0005 - First-chance exception at 0x75644B32 in App1.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000. - First-chance exception at 0x75644B32 in App1.exe: Microsoft C++ exception: Platform::COMException ^ at memory location 0x082FE670. HRESULT:0x800C0005 - First-chance exception at 0x75644B32 in App1.exe: Microsoft C++ exception: Platform::COMException ^ at memory location 0x082FDD88. HRESULT:0x800C0005 - unknown Exception

    What is happening??

    解决方案

    In the Concurrency Runtime any unhandled exception that occurs during the execution of a task is deferred for later observation. In this way, you could add a task based continuation at the end of the chain and handle errors there.

    Something like this:

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

    The call to .get triggers any exceptions that were raised in the task chain (if any). For more details you can read Exception Handling in the Concurrency Runtime.

    更多推荐

    异常处理,WinRT C ++并发异步任务

    本文发布于:2023-11-05 10:30:51,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1560592.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:异常   WinRT

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!