We have a WPF app, where:
private void SomeHandler(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(LoadItems).ContinueWith(t =>
{
//cache items to, for instance, db
}, TaskContinuationOptions.NotOnFaulted);
}
private void LoadItems()
{
//sometimes it throws an exception
//this is expected
throw new FormatException("blablabla");
}
so, in general, We use this handler to try to cache the data when a data exists.
If it does not exist then we get a Formatexception. We don't care about the result, just "fire and forget" strategy.
I've got recently two log files from clients, where I saw that the FormatException was propagated to CurrentDomain_UnhandledException handler. All clients are on Windows XP with .Net 4.0.
So the question is why is it so? Is it as designed?
This is the expected behavior on .Net 4.0. If there is a Task with an exception and that exception is never observed, it's rethrown when the Task is finalized.
If you have .Net 4.5 installed and you want to get this behavior (for example for testing), add <ThrowUnobservedTaskExceptions> to app.config.
If you want to make sure unobserved Task exceptions aren't rethrown, even on .Net 4.0, you can use TaskScheduler.UnobservedTaskException:
TaskScheduler.UnobservedTaskException += (o, args) => args.SetObserved();
But I think that the best option here is to explicitly observe the exception. You can do that by removing the NotOnFaulted option and checking the Exception property instead:
Task.Factory.StartNew(LoadItems).ContinueWith(t =>
{
if (t.Exception == null)
{
//cache items to, for instance, db
}
});
Related
I created uwp app(.Net native) for Windows 10 desktop. I use HockeyApp for collect live crash reports. Stack trace not informative. This is a long-standing problem and it does not have a solution. I tried this but it not working.
I get these exceptions:
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
Arg_NullReferenceException
Microsoft.HockeyApp.Extensibility.Windows.UnhandledExceptionTelemetryModule.CoreApplication_UnhandledErrorDetected
The parameter is incorrect. The parameter is incorrect.
On my computer the application works stably. Perhaps this is due to the versions of Windows. also I think that this is due to my xaml. It is very important for me to correct these mistakes. But I can not refuse the table.
Any ideas how can I find the source of these errors?
Sorry, this may not be an answer but I don't have enough room in the comments box.
Try the following in your App.xaml.cs. Add a handler to these events and see if they report something back to you about crashes.
public App()
{
UnhandledException += OnUnhandledException;
TaskScheduler.UnobservedTaskException += OnUnobservedException;
InitializeComponent();
}
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// Occurs when an exception is not handled on the UI thread.
// if you want to suppress and handle it manually,
// otherwise app shuts down.
e.Handled = true;
}
private static void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
{
// Occurs when an exception is not handled on a background thread.
// ie. A task is fired and forgotten Task.Run(() => {...})
// suppress and handle it manually.
e.SetObserved();
}
This code throws an exception. Is it possible to define an application global handler that will catch it?
string x = await DoSomethingAsync();
Using .net 4.5 / WPF
This is actually a good question, if I understood it correctly. I initially voted to close it, but now retracted my vote.
It is important to understand how an exception thrown inside an async Task method gets propagated outside it. The most important thing is that such exception needs to be observed by the code which handles the completion of the task.
For example, here is a simple WPF app, I'm on NET 4.5.1:
using System;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApplication_22369179
{
public partial class MainWindow : Window
{
Task _task;
public MainWindow()
{
InitializeComponent();
AppDomain.CurrentDomain.UnhandledException +=
CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException +=
TaskScheduler_UnobservedTaskException;
_task = DoAsync();
}
async Task DoAsync()
{
await Task.Delay(1000);
MessageBox.Show("Before throwing...");
GCAsync(); // fire-and-forget the GC
throw new ApplicationException("Surprise");
}
async void GCAsync()
{
await Task.Delay(1000);
MessageBox.Show("Before GC...");
// garbage-collect the task without observing its exception
_task = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
}
void TaskScheduler_UnobservedTaskException(object sender,
UnobservedTaskExceptionEventArgs e)
{
MessageBox.Show("TaskScheduler_UnobservedTaskException:" +
e.Exception.Message);
}
void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
MessageBox.Show("CurrentDomain_UnhandledException:" +
((Exception)e.ExceptionObject).Message);
}
}
}
Once ApplicationException has been thrown, it goes unobserved. Neither TaskScheduler_UnobservedTaskException nor CurrentDomain_UnhandledException gets invoked. The exception remains dormant until the _task object gets waited or awaited. In the above example it never gets observed, so TaskScheduler_UnobservedTaskException will be invoked only when the task gets garbage-collected. Then this exception will be swallowed.
The old .NET 4.0 behavior, where the AppDomain.CurrentDomain.UnhandledException event gets fired and the app crashes, can be enabled by configuring ThrowUnobservedTaskExceptions in app.config:
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>
</configuration>
When enabled this way, AppDomain.CurrentDomain.UnhandledException will still be fired after TaskScheduler.UnobservedTaskException when the exception gets garbage-collected, rather than on the spot where it thrown.
This behavior is described by Stephen Toub in his "Task Exception Handling in .NET 4.5" blog post. The part about task garbage-collection is described in the comments to the post.
That's the case with async Task methods. The story is quite different for async void methods, which are typically used for event handlers. Let's change the code this way:
public MainWindow()
{
InitializeComponent();
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
this.Loaded += MainWindow_Loaded;
}
async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
await Task.Delay(1000);
MessageBox.Show("Before throwing...");
throw new ApplicationException("Surprise");
}
Because it's async void there's no Task reference to hold on to (so there's nothing to be possibly observed or garbage-collected later). In this case, the exception is thrown immediately on the current synchronization context. For a WPF app, Dispatcher.UnhandledException will be fired first, then Application.Current.DispatcherUnhandledException, then AppDomain.CurrentDomain.UnhandledException. Finally, if none of these events are handled (EventArgs.Handled is not set to true), the app will crash, regardless of the ThrowUnobservedTaskExceptions setting. TaskScheduler.UnobservedTaskException is not getting fired in this case, for the same reason: there is no Task.
EDITED as per #Noseration's comment
In .NET 4.5 in async code you can handle unobserved exceptions by registering a handler for the TaskScheduler.UnobservedTaskException event. An exception is deemed unobserved if you do not access the Task.Result, Task.Exception properties and you do not call Task.Wait.
After the unobserved exception reaches the TaskScheduler.UnobservedTaskException event handler, the default behaviour is to swallow this exception so the program does not crash. This behaviour can be changed in the configuration file by adding the following:
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>
</configuration>
Binding an event to the AppDomain.CurrentDomain.FirstChanceException will guarantee you that your exception will be caught. As #Noseratio pointed out, you'll be notified of every exception in your application, even if the exception is handled gracefully within a catch block and the application continues on.
However, I still see this event being useful for at least capturing the last few exceptions thrown before an application halted or perhaps some other debugging scenario.
If you want to protect yourself against this
string x = await DoSomethingAsync();
My advice to you is, don't do that, add a try catch block :-)
You can always do the following to handle the exception using Application.DispatcherUnhandledException method. Of course it would be given to you inside a TargetInvocationException and might not be as pretty as other methods. But it works perfectly fine
_executeTask = executeMethod(parameter);
_executeTask.ContinueWith(x =>
{
Dispatcher.CurrentDispatcher.Invoke(new Action<Task>((task) =>
{
if (task.Exception != null)
throw task.Exception.Flatten().InnerException;
}), x);
}, TaskContinuationOptions.OnlyOnFaulted);
Well, how would you define an application global handler to deal with an exception in this case?
string x = DoSomething();
Chances are the answer to your question is exactly the same. It appears you are properly awaiting an async method, and the compiler goes to great lengths to ensure that any exception that occurs in the async method is propagated and unwound in a way that allows you to handle it just like you would in synchronous code. This is one of the primary benefits of async/await.
I'm reviewing some WPF code of my colleagues, which is a library of UserControl-based components with a lot of async void event and command handlers. These methods currently do not implement any error handling internally.
The code in a nutshell:
<Window.CommandBindings>
<CommandBinding
Command="ApplicationCommands.New"
Executed="NewCommand_Executed"/>
</Window.CommandBindings>
private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
// do some fake async work (and may throw if timeout < -1)
var timeout = new Random(Environment.TickCount).Next(-100, 100);
await Task.Delay(timeout);
}
Exceptions thrown but not observed inside NewCommand_Executed can only be handled on a global level (e.g., with AppDomain.CurrentDomain.UnhandledException). Apparently, this is not a good idea.
I could handle exceptions locally:
private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
try
{
// do some fake async work (throws if timeout < -1)
var timeout = new Random(Environment.TickCount).Next(-100, 100);
await Task.Delay(timeout);
}
catch (Exception ex)
{
// somehow log and report the error
MessageBox.Show(ex.Message);
}
}
However, in this case the host app's ViewModel would be unaware of errors inside NewCommand_Executed. Not an ideal solution either, plus the error reporting UI shouldn't always be a part of the library code.
Another approach is to handle them locally and fire a dedicated error event:
public class AsyncErrorEventArgs: EventArgs
{
public object Sender { get; internal set; }
public ExecutedRoutedEventArgs Args { get; internal set; }
public ExceptionDispatchInfo ExceptionInfo { get; internal set; }
}
public delegate void AsyncErrorEventHandler(object sender, AsyncErrorEventArgs e);
public event AsyncErrorEventHandler AsyncErrorEvent;
private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
ExceptionDispatchInfo exceptionInfo = null;
try
{
// do some fake async work (throws if timeout < -1)
var timeout = new Random(Environment.TickCount).Next(-100, 100);
await Task.Delay(timeout);
}
catch (Exception ex)
{
// capture the error
exceptionInfo = ExceptionDispatchInfo.Capture(ex);
}
if (exceptionInfo != null && this.AsyncErrorEvent != null)
this.AsyncErrorEvent(sender, new AsyncErrorEventArgs {
Sender = this, Args = e, ExceptionInfo = exceptionInfo });
}
I like the last one the most, but I'd appreciate any other suggestions as my experience with WPF is somewhat limited.
Is there an established WPF pattern to propagate errors from async void command handlers to ViewModal?
Is it generally a bad idea to do async work inside WPF command handlers, as perhaps they're intended for quick synchronous UI updates?
I'm asking this question in the context of WPF, but I think it may as well apply to async void event handlers in WinForms.
The issue here is that your UserControl library is not architected in a Typical MVVM way. Commonly, for non-trivial commands, your UserControl's code would not bind to commands directly, but instead would have properties that when set (through binding to a ViewModel) would trigger the action in the control. Then your ViewModel would bind to the application command, and set the appropriate properties. (Alternatively, your MVVM framework may have another message passing scenario that can be leveraged for interaction between the ViewModel and View).
As for Exceptions that are thrown inside the UI, I again feel that there is an architecture issue. If the UserControl is doing more than acting as a View, (i.e. running any kind of business logic that might cause unanticipated exceptions) then this should be separated into a View and a ViewModel. The ViewModel would run the logic and could either be instantiated by your other application ViewModels, or communicate via another method (as mentioned above).
If there are exceptions being thrown by the UserControl's layout / visualization code then this should (almost without exception) not be caught in any way by your ViewModel. This should, as you mentioned, only be handled for logging by a global level handler.
Lastly, if there truly are known 'exceptions' in the Control's code that your ViewModel needs to be notified about, I suggest catching the known exceptions and raising an event/command and setting a property. But again, this really shouldn't be used for exceptions, just anticipated 'error' states.
The propagation of exceptions about which the users are almost 100% unaware is not a good practice in my opinion. See this
I see the two options you really have since WPF doesn't provide any out of the box mechanisms of such the notifying of any problems:
The way you already offered with catching and firing the event.
Return the Task object from the async method (in your case, it seems that you will have to expose it through the property). The users will be able to check if there were any errors during the execution and attach a continuation task if they want. Inside the handler you can catch any exceptions and use TaskCompletionSource to set the result of the handler.
All in all you have to write some xml-comments for such a code, because that's not so easy to understand it.
The most important thing is that you should never (almost) throw any exceptions from any secondary threads.
In previous versions of MonoTouch, I used to do this to ignore unobserved exceptions:
TaskScheduler.UnobservedTaskException += delegate(object sender, UnobservedTaskExceptionEventArgs e) {
Console.WriteLine (e);
e.SetObserved ();
};
Whether it is a good practice is debatable but I'd like to know to achieve the same effect with async/await keywords now officially supported in Xamarin.iOS 6.4.
Here is the code I use for testing:
async void OnClick (object sender, EventArgs e)
{
await Task.Run (() => { throw new Exception (); });
}
When I run it, debugger pauses in AsyncVoidMethodBuilder:
I read that .NET 4.5 supposedly changed the behaviour so unobserved exceptions don't crash the app—but this doesn't help if exceptions are posted to UIKit synchronisation context where I can't handle them.
Is there a way to ignore unobserved exceptions from await in MonoTouch?
This is the correct behavior of async void methods: they are supposed to raise the exception on the SynchronizationContext that was active at the time the async void method started.
The change you mentioned in .NET 4.5 is dealing only with unobserved task exceptions, and does not apply to async void methods.
In the (Microsoft) .NET world, different SynchronizationContext implementations have different top-level error handling. WPF, WinForms, and ASP.NET all have different ways of handling that error, usually as part of an Application type.
I looked through Mono's UIKit API - though I'm not a regular Mono user - and couldn't find any top-level error handling in UIApplication, and UIKitSynchronizationContext looks like it's not public (or at least not documented).
Another way of looking at this problem: the exception handling behavior for async void methods is designed to be just like event handlers would have (for more info, see my MSDN article). So you can answer the question with another question: in UIKit, how would you handle this exception?
void OnClick (object sender, EventArgs e)
{
throw new Exception();
}
You would handle your async void exception in exactly the same way.
Alternatively, if you want to keep using UnobservedTaskException, you can simply not observe the task exception (in your async void code, Task.Run returns a task that gets an exception, and you're observing it by using await):
void OnClick (object sender, EventArgs e)
{
Task.Run(() => { throw new Exception(); });
}
However, I recommend using async void for event handlers and (eventually) awaiting all your tasks. This will ensure you aren't getting any "silent errors" (ignored task exceptions) where your program just stops working correctly and you don't know why.
This is a follow up to my initial question and I would like to present my findings and ask for corrections, ideas and insights. My findings (or rather interpretations) come from people's answers to my previous question, reading MSDN .NET 3.5 documentation and debugging .NET 3.5 code. I hope this will be of value to someone who was wondering like me how to detect when an application terminates.
Events:
System.AppDomain.CurrentDomain.ProcessExit: raised when process exits, e.g. after the default AppDomain and everything else was unloaded [Total execution time is limited to just 3 seconds!]. For WPF, use System.Windows.Application.Exit instead. For Windows Forms, run code after Application.Run(...) in main method.
System.AppDomain.CurrentDomain.DomainUnload: raised when an AppDomain other than default AppDomain unloads, e.g. when running classes with unit testing frameworks (MbUnit with TestDriven.NET).
System.AppDomain.CurrentDomain.UnhandledException: (if handled in default AppDomain:) raised for any unhandled exception in any thread, no matter what AppDomain the thread started in. This means, this can be used as the catch-all for all unhandled exceptions.
System.Windows.Application.Exit: raised when WPF application (i.e. the default AppDomain) exits gracefully. Override System.Windows.Application.OnExit to take advantage of it.
Finalizers (destructors in C#): run when garbage collector frees unmanaged resources. [Total execution time is limited!].
Order of events:
WPF application: graceful exit
System.Windows.Application.Exit
System.AppDomain.CurrentDomain.ProcessExit
Finalizers
WPF application: unhandled exception
System.AppDomain.CurrentDomain.UnhandledException
MbUnit running inside TestDriven.NET: passed test (graceful exit)
System.AppDomain.CurrentDomain.DomainUnload
Finalizers
MbUnit running inside TestDriven.NET: failed test (unhandled exceptions are handled by MbUnit)
AppDomain.CurrentDomain.DomainUnload
Finalizers
Questions:
Are my interpretations/findings correct?
Do you know of more details that I have
left out? E.g. what is the total
execution time for finalizers?
Do you know of any other events /
ideas that I be aware of?
What events are there and what order do they get raised in other applications, e.g. Windows Forms, Web Service, ASP.NET web site, etc?
Prompted by ssg31415926's question/answer (this question is a bit reversed), there's also Application.SessionEnding which is called when the when the user logs off or shuts down. It is called before the Exit event.
When Dispatcher.BeginInvokeShutdown() is called, Application.Exit will not be called.
The default timeout for a finalizer's execution is 2 seconds.
You write:
System.AppDomain.CurrentDomain.UnhandledException: (if handled in default AppDomain:) raised for any unhandled exception in any thread, no matter what AppDomain the thread started in. This means, this can be used as the catch-all for all unhandled exceptions.
I do not think that this is correct. Try the following code:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AppDomainTestingUnhandledException
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
(sender, eventArgs) => Console.WriteLine("Something went wrong! " + args);
var ad = AppDomain.CreateDomain("Test");
var service =
(RunInAnotherDomain)
ad.CreateInstanceAndUnwrap(
typeof(RunInAnotherDomain).Assembly.FullName, typeof(RunInAnotherDomain).FullName);
try
{
service.Start();
}
catch (Exception e)
{
Console.WriteLine("Crash: " + e.Message);
}
finally
{
AppDomain.Unload(ad);
}
}
}
class RunInAnotherDomain : MarshalByRefObject
{
public void Start()
{
Task.Run(
() =>
{
Thread.Sleep(1000);
Console.WriteLine("Uh oh!");
throw new Exception("Oh no!");
});
while (true)
{
Console.WriteLine("Still running!");
Thread.Sleep(300);
}
}
}
}
As far as I can tell, the UnhandledException handler is never called, and the thread will just silently crash (or nag at you if you run it in the debugger).
Just add a new event on your main form:
private void frmMain_Load(object sender, EventArgs e)
{
Application.ApplicationExit += new EventHandler(this.WhenItStopsDoThis);
}
private void WhenItStopsDoThis(object sender, EventArgs e)
{
//Program ended. Do something here.
}