Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to understand what is going on with exceptions that are thrown within a task object and never handled.

On MSDN it said that:

If you do not wait on a task that propagates an exception, or access its Exception property, the exception is escalated according to the .NET exception policy when the task is garbage-collected.

So I don't quite understand in what way those exceptions affect program flow. I thought that those exceptions should interrupt execution as soon as they are garbage-collected. But I can not design this behaviour. Within the following snippet the thrown exception doesn't show up.

// Do something ...
Task.Run (()=> {throw new Exception("Exception in the task!");});
// Do something else

Please, can anyone explain how unhandled task exception are dealt with and how they affect program flow.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
311 views
Welcome To Ask or Share your Answers For Others

1 Answer

You're describing the behavior as it was in .NET 4, but it will be difficult for you to force the garbage collection and actually observe that behavior. The following quote from Stephen Toub's excelent write-up on the subject should make it even more clear:

Tasks keep track of whether an unhandled exception has been “observed.” In this context, “observed” means that code has joined with the Task in some fashion in order to at least be made aware of the exception. This could be calling Wait/WaitAll on the Task. It could be checking the Task’s Exception property after the Task has completed. Or it could be using a Task’s Result property. If a Task sees that its exception has been observed in some manner, life is good. If, however, all references to a Task are removed (making the Task available for garbage collection), and if its exception hasn’t yet been observed, the Task knows that its exception will never be observed. In such a case, the Task takes advantage of finalization, and uses a helper object to propagate the unhandled exception on the finalizer thread. With the behavior described earlier, that exception on the finalizer thread will go unhandled and invoke the default unhandled exception logic, which is to log the issue and crash the process.

He also suggested two useful extension methods for handling exceptions in "fire-and-forget" tasks: one ignoring the exception and the other one immediately crashing the process:

public static Task IgnoreExceptions(this Task task)
{
    task.ContinueWith(c => { var ignored = c.Exception; },
        TaskContinuationOptions.OnlyOnFaulted |
        TaskContinuationOptions.ExecuteSynchronously |
        TaskContinuationOptions.DetachedFromParent);
    return task;
}

public static Task FailFastOnException(this Task task)
{
    task.ContinueWith(c => Environment.FailFast(“Task faulted”, c.Exception),
        TaskContinuationOptions.OnlyOnFaulted |
        TaskContinuationOptions.ExecuteSynchronously |
        TaskContinuationOptions.DetachedFromParent);
    return task;
}

In .NET 4.5 the default behavior has changed. Again, a quote from another Stephen Toub's post on the subject (thanks to mike z for bringing it to my attention in the comments):

To make it easier for developers to write asynchronous code based on Tasks, .NET 4.5 changes the default exception behavior for unobserved exceptions. While unobserved exceptions will still cause the UnobservedTaskException event to be raised (not doing so would be a breaking change), the process will not crash by default. Rather, the exception will end up getting eaten after the event is raised, regardless of whether an event handler observes the exception. This behavior can be configured, though.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...