34

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

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

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

建议的解决方法是让 VS 中断所有异常,而不仅仅是未处理的异常。它的工作原理是令人讨厌的“副作用”,它确实会在所有异常情况下中断:)

是否有另一种不涉及中断所有异常的解决方法?它可以特定于 MVC,但不一定是(意味着它是否是适用于 MVC 的通用解决方案)。

4

5 回答 5

3

A) 包装您的调用并在您的任务代码中抛出一个自定义异常。中断只抛出您的自定义异常。您可以选择第一次抛出的异常。

乙)。Debug.Assert() 你的任务结果,如果你有任何等待代码。即,不仅仅是射击和遗忘。如果您在某处等待任务或继续坚持错误处理,任务会在属性中返回异常。

伪代码即任务。continuewith(r => if(!r.Exception is null) Debug.Break())) 等。

希望这可以帮助您走上正确的道路。

于 2013-10-07T14:51:19.370 回答
2

You could try and listen for this event if nothing else works here

AppDomain.CurrentDomain.UnhandledException

or

AppDomain.CurrentDomain.FirstChanceException

Then you need to put some if-constructs (check what sender for example) to hit your breakpoint only when it makes sense.

于 2013-10-07T17:05:23.153 回答
2

MSDN 中的try-catch 参考对异步方法中的异常有一些指导和示例,并指出:“由于返回任务的方法中存在未处理的异常,应用等待的已完成任务可能处于错误状态。等待该任务引发异常。”

对于该页面上给出的示例,它指出:“以下示例说明了异步方法的异常处理。要捕获异步任务引发的异常,请将await表达式放在try块中,并在catch块中捕获异常。取消注释throw new Exception示例中的行以演示异常处理。任务的IsFaulted属性设置为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
于 2013-10-07T19:12:59.347 回答
1

正如此处所建议的,启用“仅我的代码”是执行此操作的一种方法。诚然,这些异常在技术上不是未处理的,但它们是由用户代码未处理的,这让 VS 做有用的事情并向您显示异常发生的位置。

请参阅此答案以获取一些屏幕截图。

显然这个设置有其他含义(例如你不能再单步执行框架代码),所以这可能合适也可能不合适。

于 2016-04-05T10:14:07.633 回答
0

您可以为TaskScheduler.UnobservedTaskException.

但是,也许您已经尝试过,并且想要一种方法使调试器在原始异常处中断,而不是在未观察到的任务异常处理程序中中断。

于 2013-10-14T01:39:18.503 回答