How can I make VS break on exceptions in an async Task, without breaking on all exceptions?

前端 未结 5 686
小蘑菇
小蘑菇 2021-02-01 15:06

As indicated here and here, exceptions occuring in an async Task are technically not unhandled.

This is particularly nasty when working with MVC. It actually took us a w

相关标签:
5条回答
  • 2021-02-01 15:27

    The try-catch reference in MSDN has some guidance and examples on exceptions in async methods, and states: "The completed task to which await is applied might be in a faulted state because of an unhandled exception in the method that returns the task. Awaiting the task throws an exception."

    For the example given on that page, it states: "The following example illustrates exception handling for async methods. To catch an exception that an async task throws, place the await expression in a try block, and catch the exception in a catch block. Uncomment the throw new Exception line in the example to demonstrate exception handling. The task's IsFaulted property is set to True, the task's Exception.InnerException property is set to the exception, and the exception is caught in the catch block."

    Here's the copy from the example given there:

    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
    
    0 讨论(0)
  • 2021-02-01 15:28

    A) Wrap your calls and throw a custom Exception in your Task code. Break on only throw of your custom exception. You can select the Exceptions for first throw.

    B). Debug.Assert() your Task Results, if you have any wait code. i.e., not just firing and forgetting. Tasks return the Exceptions in a property if you wait on them somewhere or stick error handling in a continuation.

    psuedo code i.e. task. continuewith(r => if(!r.Exception is null) Debug.Break())) etc.

    Hope that helps you on the right path.

    0 讨论(0)
  • 2021-02-01 15:34

    You could add a handler for TaskScheduler.UnobservedTaskException.

    However, perhaps you've already tried that and you want a way to make the debugger break at the original exception rather than in the unobserved task exception handler.

    0 讨论(0)
  • 2021-02-01 15:40

    Enabling "Just My Code" is one way to do this, as suggested here. True, the exceptions are technically not unhandled, but they are unhandled by user code, which gets VS to do the useful thing and show you where the exception occurred.

    See this answer for some screenshots.

    Obviously this setting has other implications (e.g. you can no longer step through framework code), so this may or may not be suitable.

    0 讨论(0)
  • 2021-02-01 15:45

    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.

    0 讨论(0)
提交回复
热议问题