如何在异步任务中使VS中断异常,而不会破坏所有异常?

时间:2013-09-23 12:11:49

标签: c# asp.net-mvc visual-studio-2012

如上所示herehere,异步任务中发生的异常在技术上并非未处理。

使用MVC时尤其令人讨厌。它实际上花了我们一段时间来弄清楚它为什么越来越多地发生异常没有被捕获,我们在过去几周内逐渐将Web API调用引入我们的应用程序。

public async Task<ActionResult> Foo()
{
    // ...
}

建议的解决方法是使VS中断所有异常而不是仅处理未处理的异常。它有效,令人讨厌的“副作用”确实在所有例外情况下确实破坏了:)

是否有其他解决方法不涉及打破所有异常?它可以特定于MVC但不一定是(这意味着它是一个适用于MVC的通用解决方案)。

5 个答案:

答案 0 :(得分:3)

A)包裹你的电话并在你的任务代码中抛出一个自定义的例外。打破你的自定义异常。您可以选择第一次抛出的例外。

B)。 Debug.Assert()你的任务结果,如果你有任何等待代码。即,不只是射击和遗忘。如果您在某个地方等待它们或在延续中坚持错误处理,任务将返回属性中的异常。

伪造的代码 即任务。 continuewith(r =&gt; if(!r.Exception为null)Debug.Break())) 等

希望能帮助你走上正确的道路。

答案 1 :(得分:2)

如果此处没有其他工作,您可以尝试收听此事件

AppDomain.CurrentDomain.UnhandledException

AppDomain.CurrentDomain.FirstChanceException

然后你需要设置一些if-constructs(例如检查发送者),只有在有意义的时候点击你的断点。

答案 2 :(得分:2)

try-catch reference in MSDN对异步方法中的异常有一些指导和示例,并说明:“应用await的已完成任务可能处于故障状态,因为返回任务的方法中存在未处理的异常等待任务抛出异常。“

对于该页面上给出的示例,它指出:“以下示例说明了异步方法的异常处理。要捕获异步任务抛出的异常,请将等待表达式放在尝试阻止,并在 catch 块中捕获异常。取消注释示例中的throw new Exception行以演示异常处理。任务的 IsFaulted property设置为 True ,任务的 Exception.InnerException 属性设置为异常,异常将在 catch 块中捕获。

以下是那里给出的例子的副本:

public async Task DoSomethingAsync()
{
    Task<string> theTask = DelayAsync();

    try
    {
        string result = await theTask;
        Debug.WriteLine("Result: " + result);
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception Message: " + ex.Message);
    }
    Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
    Debug.WriteLine("Task IsFaulted:  " + theTask.IsFaulted);
    if (theTask.Exception != null)
    {
        Debug.WriteLine("Task Exception Message: "
            + theTask.Exception.Message);
        Debug.WriteLine("Task Inner Exception Message: "
            + theTask.Exception.InnerException.Message);
    }
}

private async Task<string> DelayAsync()
{
    await Task.Delay(100);

    // Uncomment each of the following lines to 
    // demonstrate exception handling. 

    //throw new OperationCanceledException("canceled");
    //throw new Exception("Something happened.");
    return "Done";
}

// Output when no exception is thrown in the awaited method: 
//   Result: Done 
//   Task IsCanceled: False 
//   Task IsFaulted:  False 

// Output when an Exception is thrown in the awaited method: 
//   Exception Message: Something happened. 
//   Task IsCanceled: False 
//   Task IsFaulted:  True 
//   Task Exception Message: One or more errors occurred. 
//   Task Inner Exception Message: Something happened. 

// Output when a OperationCanceledException or TaskCanceledException 
// is thrown in the awaited method: 
//   Exception Message: canceled 
//   Task IsCanceled: True 
//   Task IsFaulted:  False

答案 3 :(得分:1)

启用&#34;只是我的代码&#34;是建议here建议的一种方法。确实,例外在技术上并非未处理,但它们未处理由用户代码 ,这使得VS可以执行有用的操作并向您显示异常发生的位置。

有关屏幕截图,请参阅this answer

显然,此设置还有其他含义(例如,您无法再单步执行框架代码),因此这可能适用也可能不适用。

答案 4 :(得分:0)

您可以为TaskScheduler.UnobservedTaskException添加处理程序。

但是,您可能已经尝试过这种方法,并希望有一种方法可以使调试器在原始异常处中断,而不是在未观察到的任务异常处理程序中。