Typically, for code that I don't expect to throw exceptions but does (i.e. a programming error), I want my application to crash (so that it doesn't corrupt data, report invalid data to the user, etc.).
Is there a best practice for getting (closer to) this behavior when using Tasks
? We've registered a handler for TaskScheduler.UnobservedTaskException
. The problem is that this can occur much later than the causing unexpected exception.
Question: Which option should I use if any:
Should I wrap my Task
s action in a try/catch and escalate in the catch for exceptions I don't expect? And if so, what should I do to escalate (i.e. I'd like to get it to fire the AppDomain.UnhandledException
event and terminate.
Should I attach a continuation (OnlyOnFaulted
) on the ui thread (this is a Winforms application) that rethrows the exception if it is not an expected exception?
Is there a better or more standard approach?
Here's what #1 might look like:
var t1 = Task.Factory.StartNew(() =>
{
try
{
string path = null; // Programming error. Should have been a valid string. Will cause System.ArgumentNullException below
using (FileStream fs = File.Create(path))
{
}
}
catch (System.IO.IOException) { throw; } // Expected possible exception
catch (System.UnauthorizedAccessException) { throw; }
catch
{
// Anything caught here is not an expected exception and should be escalated.
// But how?
}
});
Here's what #2 might look like:
TaskScheduler uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
var t1 = Task.Factory.StartNew(() =>
{
string path = null; // Programming error. Should have been a valid string. Will cause System.ArgumentNullException below
using (FileStream fs = File.Create(path))
{
}
});
t1.ContinueWith(t =>
{
Exception ex = t.Exception;
if (ex is IOException || ex is UnauthorizedAccessException) // Expected exceptions (do nothing)
return;
throw ex; // Not expected (escalate by rethrowing)
}, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiTaskScheduler);
Attaching a continuation feels like a good approach to me. If you're comfortable with the assumption that you won't be blocking the UI thread for too long for other reasons, forcing the continuation to run on the UI thread seems like a very reasonable option to me. That way you can perform any UI tasks you need to as well, as part of the emergency shutdown.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With