IHandleWithTask.Handle - Exceptions are never caught
See original GitHub issueEnvironment: WPF, .NET 4.5, Caliburn.Micro 2.0.2, Visual Studio 2013
Summary: Exceptions thrown within a task within an IHandleWithTask.Handle method do not get raised in any of the expected event handlers including TaskScheduler.UnobservedTaskException, BootstrapperBase.OnUnhandledException or Application.DispatcherUnhandledException. In fact there doesn’t seem to be any way to get the exception with the default behavior.
The EventAggregator appears to call void Handle and Task Handle with the same logic:
var result = pair.Value.Invoke(target, new[] { message }); if (result != null) { HandlerResultProcessing(target, result); }
The default HandlerResultProcessing in BootstrapperBase does nothing to deal with Task.Exception. The only way I have found to get the exceptions raised is to define a new action in HandlerResultProcessing. For example:
var a = EventAggregator.HandlerResultProcessing;
EventAggregator.HandlerResultProcessing = (o, r) =>
{
if (a != null) { a(o, r); }
var taskResult = r as Task;
if (taskResult != null)
{
taskResult.ContinueWith(r1 =>
{
if (r1.Exception != null)
{
throw r1.Exception;
}
});
}
};
Question #1: Is this the expected behavior?
Per Stephen Cleary in https://msdn.microsoft.com/en-us/magazine/JJ991977.aspx an exception in an ‘async void’ method will be caught and raised by the SynchronizationContext. So it seems better to use IHandle<EventArgs> with a method signature of async void IHandle<EventArgs>. This is after all an event handler. This goes along the lines of ‘async void OnInitialize’ in this article: http://caraulean.com/blog/2013/07/15/using-caliburn-micro-with-async-await/.
Question #2: Since IHandle and IHandleWithTask are called in the same way and IHandleWithTask does not deal with exceptions why have IHandleWithTask? Why not just use ‘async void IHandle<>.Handle’ methods?
I have a stand alone project I can send if requested.
Issue Analytics
- State:
- Created 8 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
Since Caliburn Micro library code is already wrapping most of the logic in most applications that use it, it would make sense for the framework to expose a single event handler that reports any capturable errors. There will still be errors that could be thrown where the stack trace doesn’t include Caliburn Micro (e.g., view code-behind), but those can already be handled by existing .NET events. What I’d love to see is that, at least as far as Caliburn Micro’s concerned, we get a single event handler for any exceptions that Caliburn Micro can catch.
An interesting aside: All I do when I catch an exception is display an
ErrorViewModel
that has apublic Exception Exception
property and renders theToString()
of that to a text box. The view has a Copy to Clipboard button and a Close Application button. It’s pretty easy for me to wire this up in several places, but since I’m using a Caliburn Micro view model to display exceptions, I’d prefer the event handler to be within Caliburn Micro.Created #362 as a point for doing this.