I need help identifying a generic way of catching exceptions that are thrown from within a delegate when that delegate contains a Task.Run that is throwing an exception. Currently, when I invoke a delegate (in this case a func) that is passed into another "master" method and an exception is thrown from within a Task.Run in the delegate, the exception is not caught with a try/catch in the code surrounding the invocation. The following simplified example shows the exceptions inside the delegate being caught by the try/catch inside the delegate but being "lost" elsewhere:
public static void Main()
{
AppDomain.CurrentDomain.UnhandledException += (s, e) => CurrentDomain_UnhandledException();
TaskScheduler.UnobservedTaskException += (s, e) => CurrentDomain_UnhandledException();
HandledDelegate(() => Task.Run(() =>
{
try
{
Console.WriteLine("Executed");
throw new Exception($"Caught");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw new Exception($"Caught Again");
}
}
));
}
private static void CurrentDomain_UnhandledException()
{
Console.WriteLine("Unhandled Exception Occurred.");
}
public static void HandledDelegate(Action a)
{
try
{
a.Invoke();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
Thread.Sleep(10000);
}
And the following example shows the exception not being caught within the try/catch around the invoke, and bubbling up to the app domain as an unhandled exception.
public static void Main()
{
AppDomain.CurrentDomain.UnhandledException += (s, e) => Console.WriteLine("Unhandled Exception");
HandleDelegateEx(async () => await Task.Run(() => throw new Exception("test")));
Thread.Sleep(1000);
}
public static void HandleDelegateEx(Action a)
{
try
{
a.Invoke();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
This last one is most like my current code which I need to fix. The delegates often Task the code off on a background thread and don't handle any errors (expecting them to be caught by where the delegate is invoked.
This code is used throughout the app in hundreds of locations, and few, if any, catch exceptions within the delegate (as other programmers erroneously thought that exceptions thrown by the delegate would be caught). Is there any way to catch exceptions thrown from inside these delegates without massively refactoring each and every delegate to catch exceptions?