In my App.xaml.cs I have events to handle DispatcherUnhandledExceptions (UI thread) and UnhandledException (Non UI thread). When I throw an exception inside dispatcher.Invoke, the dispatcherhandler catches the exception and handles it. I am setting e.Handled to true after logging the exception. Now the strange behaviour, if i throw the exception outside of the dispatcher.Invoke as a regualr statment, control is sent to the dispatcher exception handler,but after the method is processed the app basically loses control but I can tell its still running by looking at the stop button in vs.
one more thing, if i set e.handled to false, control is sent to the non-ui thread exception handler.
So what puzzles me is why is the application locking after handling the exceptiono in the dispatcher handler?
here's my code
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
// log exception here
e.Handled = true;
} // control is lost after executing this block
private void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
Exception ex = e.ExceptionObject as Exception;
// log exception here
}
finally
{
Environment.Exit(-1);
}
}
An UnhandledException means that your application is effectively dead. If you get that event then it is too late to do anything to recover from the scenario. Typically you would use this event only to log errors for debugging purposes and maybe attempt to cleanup some unmanaged resources.
The following article gives a detailed explanation of exception handling in WPF.
It seems like the app is able to resume operation if the exception is raised after the OnStartup Event, if the exception is raised in between, the exception is caught and handled but the main window is never shown yet the debugger shows the app as running.
the closest solution I found is to remove complex logic from the constructor of main window to allow onstartup event to execute and do a lot of loading in my MainWindow load event.
Related
I'm completing a UWP app started by someone else. The app crashes frequently and I always end up in App.g.i.cs at
if (global::System.Diagnostics.Debugger.IsAttached)
global::System.Diagnostics.Debugger.Break();
where I then have to say "no, don't start the debugger" and close 2 windows.
Is there somewhere I could put a big try/catch so that I don't have to restart the app each time this happen? I can't find anything in AppShell or App.
Or do I have to put a try/catch in every single event handler?
If you want to avoid starting the new debugger and restarting the app each time when encountering unhandled exceptions, you can use Application.UnhandledException event and set the Handled property of the event arguments to true like following:
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.UnhandledException += (sender, e) =>
{
e.Handled = true;
System.Diagnostics.Debug.WriteLine(e.Exception);
};
}
The UnhandledException event is used to notify the app about exceptions encountered by the XAML framework or by the Windows Runtime in general that have not been handled by app code.
Normally after the UnhandledException event is fired, the Windows Runtime terminates the app because the exception was unhandled. The app code has some control over this: if the UnhandledException event handler sets the Handled property of the event arguments to true, then in most cases the app will not be terminated.
For more info, please see Remarks of Application.UnhandledException event and the blog: Strategies for Handling Errors in your Windows Store Apps.
As far as i know most you cant do what you are trying to do (big try catch block) and for all intents and purposes you shouldn't even consider that possibility.
First try to determine why the app is crashing, on what page, is it when you try to something specific, the same thing everytime and then you can try catch some of the methods on that particular page and determine what's causing the crash
If you want to treat the cause rather than the symptoms, you should enable first-chance exceptions in the debugger settings. Then the debugger should break at the source of the exception, rather than in the global handler. You can then address the root cause of the problems directly.
Shipping an app that has the global handler blindly set every exception as "handled" even when you don't know why it's failing is not a good solution.
You can try/catch in your main app to catch all exceptions. Shown is an example using Xamarin Forms DisplayAlert:
try
{
//throw new Exception("gone and done it");
MyMainProgram();
}
catch (Exception ex)
{
await DisplayAlert("Whoops!", ex.Message, "ok");
throw ex;
}
You can test this by uncommenting the "throw new Exception". Execution stops with an alert you must answer, then continues by throwing the exception to prevent executing corrupted code.
In MainFile:
Window window = new MyDialogWindow();
try
{
window.ShowDialog();
}
catch
{
// This is never called !
}
In MyDialogWindow:
private void MyDialogWindow_Closing( object sender, CancelEventArgs e )
{
throw new Exception();
}
It seems that the exception thrown into the closing event handler never reach the catch block of the caller. Do you know why ?
EDIT: I should mention I've checked that MyDialogWindow_Closing is called after I press on the close button.
EDIT2: When listening to AppDomain.CurrentDomain.UnhandledException, the event is fired !
I would guess that you are getting an exception that is not your thrown exception, but instead another exception that is not normally 'caught' by the .Net exception handling umbrella. One such class of exceptions are structured error handling exceptions (SEH) which typically occur when there are issues (usually memory issues, or pointer issues) in unmanaged code that crash in that execution, but can't be bubbled up into the .Net exception handling stream.
Go into your Debug-->Exceptions, and check everything. Then run your program. You will almost certainly find out what your exception truly is.
It can't hurt to look at this question as well which discusses the topic.
I'm developing a light-weight WPF MVVM framework, and would like to be able to catch unhandled exceptions, and ideally recover from them.
Ignoring for the moment all the good arguments for not doing this, I encounter the following situation:
If I register a handler for AppDomain.CurrentDomain.UnhandledException within the OnStartup method of the App.xaml.cs, as follows...
App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(this.AppDomainUnhandledExceptionHandler);
base.OnStartup(e);
}
void AppDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs ea)
{
Exception e = (Exception)ea.ExceptionObject;
// log exception
}
and then raise an exception within one of my VM's, the handler is called as expected.
So far so good, except for the fact that there is no way that I can recover using this approach, all that I can do is log the exception and then let the CLR terminate the app.
What I actually wanted to do is to recover, and return control to the main framwork VM. (Again putting aside the motivations against doing this).
So, doing some reading, I decide to register an event handler for AppDomain.CurrentDomain.UnhandledException in the same place, so that the code now looks something like this...
protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(this.AppDomainUnhandledExceptionHandler);
this.DispatcherUnhandledException +=
new DispatcherUnhandledExceptionEventHandler(DispatcherUnhandledExceptionHandler);
base.OnStartup(e);
}
void AppDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs ea)
{
Exception e = (Exception)ea.ExceptionObject;
// log exception
}
void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args)
{
args.Handled = true;
// implement recovery
}
The issue is that once I register the handler for this.DispatcherUnhandledException, NEITHER EVENT HANDLER IS CALLED. So registering the DispatcherUnhandledExceptionHandler somehow deactivates the handler for AppDomain.CurrentDomain.UnhandledException.
Does anyone have an approach for catching and recovering from unhandled VM exceptions ?
It might be important to mention that there is no explicit use of threading in the framework.
The reason VS shows you the exception is because you have set it up like that (either you did this explicitly or - more likely - the defaults in VS configured it like this). You can control what Visual Studio does when it encounters an exception in the debugged code through the Debug->Exceptions menu.
You can even make it break even though you have a catch for it which is quite handy in some cases.
If you're not using multi threading then you should be fine with the DispatcherUnhandledException event since it will catch everything that gets uncaught on the main UI thread.
A quick answer to my own question:
This works...
App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
Application.Current.DispatcherUnhandledException +=
new DispatcherUnhandledExceptionEventHandler(DispatcherUnhandledExceptionHandler);
base.OnStartup(e);
}
void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args)
{
args.Handled = true;
// implement recovery
// execution will now continue...
}
[Edit: My comments below have nothing to with the implementation, but my specific IDE (Visual Studio) config with respect to exception catching by the IDE. Please see Isak's comments above.]
BUT, and it's a big but, if you're executing from within VisualStudio, then YOU WILL STILL GET THE VS exception notification dialog box popping up, and the DispatcherUnhandledExceptionHandler will only be invoked if you press F5/continue, after which execution will continue as per normal.
If you're running the compiled binary directly, i.e from the command line or via Windows Explorer, then the handler will be invoked as you would expect, without any intermediary popup.
Consider the following simple application: a windows form created by a "new C# windows application" sequence in VS that was modified in a following way:
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Application.Run(new Form1());
}
catch (Exception ex)
{
MessageBox.Show("An unexpected exception was caught.");
}
}
Form1.cs contains the following modifications:
private void Form1_Load(object sender, EventArgs e)
{
throw new Exception("Error");
}
If I press F5 in IDE, then, as I expect, I see a message box saying that exception was caught and the application quits.
If I go to Debug(or Release)/bin and launch the executable, I see the standard "Unhandled exception" window, meaning that my exception handler doesn't work.
Obviously, that has something to do with exception being thrown from a different thread that Application.Run is called from. But the question remains - why the behavior differs depending on whether the application has been run from IDE or from command line?
What is the best practice to ensure that no exceptions remain unhandled in the application?
Normally Application.ThreadException will handle the exception in the Load event. You'll get the ThreadExceptionDialog that offers the Quit and Continue options.
But not when a debugger is attached. The catch clause in the message loop that displays the dialog is intentionally disabled in that case. That's necessary because it would be very difficult to trouble-shoot exceptions if that dialog pops up when you debug a program. Which this catcher no longer active, your catch clause in the Main() method now gets a shot at the exception.
You can make it consistent by using Application.SetUnhandledExceptionMode() in the Main() method. You shouldn't, exceptions really are hard to debug if you do this. If you want to customize exception handling for the UI thread then you should register your own Application.ThreadException handler:
if (!System.Diagnostics.Debugger.IsAttached)
Application.ThreadException += myThreadException;
Trapping unhandled exceptions in worker threads requires a AppDomain.UnhandledException handler. They are not recoverable.
Also beware of a bug in 64-bit Windows, exceptions in the Load event are swallowed without diagnostic when a debugger is attached. Force AnyCPU mode to avoid that trap.
In addition to catching any exceptions thrown inside the Main method you must also handle AppDomain.CurrentDomain.UnhandledException and Application.ThreadException.
Not sure why the behavior differs with and without a debugger attached though.
I was unable to find an answer to this question anywhere...
What happens with the exceptions thrown in the callback method for System.Threading.Timer, (or in the event handler for System.Timers.Timer). Is the exception propagated to the thread on which the timer was created or is the exception lost?
What are the side-effects of throwing an exception within the timer's callback functions?
What would be the right way to signalize to the timer's creation thread that the exception in the worker thread (callback method) has been thrown?
Thanks for your time.
The exception is not passed back to the calling thread. If you want it to be, you can add a catch block and figure out a way to signal the calling thread. If the calling thread is a WinForms or WPF UI thread, you can use the SynchronizationContext class to pass a call to the UI thread. Otherwise, you could use a thread-safe queue (or a sync lock) and check it periodically in the other thread.
System.Timers.Timer will silently swallow exceptions and continue the timer (although this is subject to change in future versions of the framework); System.Threading.Timer will terminate the program.
I don't know what the best option is, but when I'm using a callback timer I'm normally throwing exceptions and letting them bubble up to the main callback routine, where I handle them gracefully. The thread continues to run on the timer as it should.
Unhandled exceptions in the thread (System.Threading.Timer) will stop your entire program.
I dont know if it is a best solution, but what I did was a small workaround. My calling thread has subscribed to an event for catching exceptions from across the threads. So when exception occurs in some thread, say in TimerElapsed event, then form the catch block I raise the event passing exception object as an argument to the event.
EventHolderCallingClass: It must define delegate and event as shown below.
public class EventHolderCallingClass
{
public delegate void HandleExceptionEventDelegate(Exception exception);
public event HandleExceptionEventDelegate HandleExceptionEvent ;
void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
//some operation which caused exception.
}
catch(Exception exception)
{
if(HandleExceptionEvent!=null)
HandleExceptionEvent(exception)
}
}
}
Event Handler Class (Exception Handler):
public EventHandlerClassConstructor()
{
EventHolderCallingClass.HandleExceptionEvent += new EventHolderCallingClass.HandleExceptionEventDelegate(HandleExceptionEventHandler);
}
void HandleExceptionEventHandler(Exception exception)
{
//handle exception here.
}
From my humble test under windows 10 framework 4.6, the thread used by the SystemTimers.Timer elapsed event will not propagate the unhandled exception.
I needed to fire a event to the main thread to notify the unhandled exception happened.