【问题标题】:C# await and catch exceptionC# 等待并捕获异常
【发布时间】:2015-07-17 16:30:21
【问题描述】:

我在这里看到很多人谈论从异步函数中捕获异常的方法,但我没有任何工作。

我用一些代码制作了一个 IRC 机器人:https://github.com/BenFradet/RiotSharp (由于异常是从WebException 继承的,如果你想测试它应该做同样的事情)

所以我尝试了异步函数。当 RiotApi 中的函数找不到用户时,例如 GetSummoner(),会抛出 404 作为 RiotSharpException

try
{
    RiotSharp.SummonerEndpoint.Summoner summoner = api.GetSummoner(region,name);
    SendSummonersDetails(summoner, e.Message.MessageTarget);
}
catch (RiotSharpException ex)
{
    string error = string.Format(this.RegionNotFound, command[2]);
    irc.Send(new IRCMessage("PRIVMSG", e.Message.MessageTarget, error));
}

我已经使用了很多次,我可以捕捉到 404。 然而,如果我使用异步版本: 我要不要去

try
{
    RiotSharp.SummonerEndpoint.Summoner summoner = await api.GetSummonerAsync(region,name);
    SendSummonersDetails(summoner, e.Message.MessageTarget);
}
catch (RiotSharpException ex)
{
    string error = string.Format(this.RegionNotFound, command[2]);
    irc.Send(new IRCMessage("PRIVMSG", e.Message.MessageTarget, error));
}

或者对于 Task 然后离开,try/catch 不会捕获异常。

我尝试了在这里看到的所有内容: Catch an exception thrown by an async void method

我也尝试了ContinueWith TaskContinuationOptions.OnlyOnFaulted,但也没有用。

我使用 VS 2013 和框架 4.5ish

我很迷茫,用了我在这里找到的所有东西,但没有任何效果,也许有人能想到点什么?!

【问题讨论】:

  • 异常不会在异步版本中被捕获,除非您尝试对返回的任务对象执行某些操作,事实上,任务的异常属性应该提供具有内部异常的 AggregateException,其中将包含特定的你需要的例外。使用任何 Task 对象方法,如 Result 和 catch 都会得到异常。这是 TPL 的行为。
  • 您在问题中包含的异步版本(即您在哪里await 操作)应该像同步版本一样抛出异常。如果没有,那是您正在使用的 RiotApi 组件中的一个错误。如果没有a good, minimal, complete code example,我看不到任何更具体的评论方式,别介意回答这个问题。
  • 您还可以捕获通用异常或聚合异常并检查吗,因为异步调用将引发聚合异常,而不是您期望的 Riot 异常,如前所述,您已经从中获得了异常
  • 我下载了 VS 的 RC 2105,同样的代码运行良好……我不明白 :(
  • VS 13 有效。异步异常处理适用于数十万个生产部署。 VS 15 还没有准备好。而不是假设在完整可重现代码和完整结果之后发生了如此重大的事情。堆栈跟踪可能包含 AggregateException 中的异常 2 级,但没人能猜到

标签: c# exception asynchronous


【解决方案1】:

尝试类似:

               try
               {
                    RiotSharp.SummonerEndpoint.Summoner summoner = await api.GetSummonerAsync(region,name);
                    SendSummonersDetails(summoner, e.Message.MessageTarget);
                }
                catch (AggregateException ex)
                {
                  foreach(Exception ee in ex.InnerExceptions)
                  {
                    RiotException e = ee as RiotException;
                    string error = string.Format(this.RegionNotFound, command[2]);
                    irc.Send(new IRCMessage("PRIVMSG", e.Message.MessageTarget, error));
                  } 

                 }

【讨论】:

  • 我已经尝试过了,因为我在这里读到了 5 个类似的错误。它不起作用,但它在 4.6 框架和 VS 15 中工作。我在某处读到 VS 13 不支持这一点,我开始相信......但感谢您的帮助!
  • 实际上它在数十万次部署中的生产环境中运行良好。您确实需要发布重现错误的代码 - 包括任何未处理的异常处理程序。可能只是你使用的项目有问题
  • 如果你想看的话,我可以把整个 VS 项目发给你。然而它不是我使用VS2015(我在2015年加载了确切的项目并且它第一次工作)现在它在我切换回来时与2013一起工作。要么我是个大傻瓜(很可能......他,大多数错误来自椅子和键盘之间)要么我遇到了一个奇怪的错误
【解决方案2】:

它似乎在 2015 RC 与 4.6 框架上运行良好......所以我会坚持下去

【讨论】:

  • 异步方法中的异常处理没有任何问题。很可能GetSummonerAsync 方法会抛出与您想象的不同的异常。
  • 未处理的异常是我所期待的(我也尝试了 Exception ,它是根目录并且应该可以工作)我尝试了与 VS 2015 完全相同的代码,它捕获得很好。我无言以对 :( 你所有的解决方案都运行良好,但在 VS15 上
猜你喜欢
  • 2017-08-08
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
  • 2015-09-27
相关资源
最近更新 更多