WPF - DispatcherUnhandledException does not seem to work - wpf

I started a new WPF project in VS2008 and then added some code to trap DispatcherUnhandledException. Then I added a throw exception to Window1
but the error is not trapped by the handler. Why?
public App()
{
this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
System.Windows.MessageBox.Show(string.Format("An error occured: {0}", e.Exception.Message), "Error");
e.Handled = true;
}
void Window1_MouseDown(object sender, MouseButtonEventArgs e)
{
throw new NotImplementedException();
}

This can happen because of the way you have the debugger handling exceptions -- Debug/Exceptions... should allow you to configure exactly how you want it handled.

Look at following msdn link http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx
Following is Relevant here
If an exception is not handled on either a background user interface (UI) thread (a thread with its own Dispatcher) or a background worker thread (a thread without a Dispatcher), the exception is not forwarded to the main UI thread. Consequently, DispatcherUnhandledException is not raised. In these circumstances, you will need to write code to do the following:
Handle exceptions on the background thread.
Dispatch those exceptions to the main UI thread.
Rethrow them on the main UI thread without handling them to allow DispatcherUnhandledException to be raised.

This is how I handle it. This isn't pretty but keep in mind that this type of error should never make it past debugging as a dev. Those errors should be long resolved before you go to production (so its okay that this isn't pretty). In the Startup project, in the App.xaml (App.xaml.cs) code behind, I put the following code.
OnStartup, create a DispatcherUnhandledException event handler
In the handler, use a MessageBox to display the message. Note that its likely the startup window has not yet been created so don't try to put it in a window.
e.Handle the error
I like to see when there are additional internal errors so I continue to call the display window until the internal error is null.
I'm not sure why the code block special characters aren't formatting this correctly. Sorry about that.
protected override void OnStartup(StartupEventArgs e)
{
// define application exception handler
Application.Current.DispatcherUnhandledException +=
AppDispatcherUnhandledException;
// defer other startup processing to base class
base.OnStartup(e);
}
private void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
runException(e.Exception);
e.Handled = true;
}
void runException(Exception ex)
{
MessageBox.Show(
String.Format(
"{0} Error: {1}\r\n\r\n{2}",
ex.Source, ex.Message, ex.StackTrace,
"Initialize Error",
MessageBoxButton.OK,
MessageBoxImage.Error));
if (ex.InnerException != null)
{
runException(ex.InnerException);
}
}

At first, even outside the debugging environment, my handler does not seem to be triggering.....then I realized I forget to set e.Handled = true.
In truth it was working but because e.Handled was still false the standard exception handler still kicked in and did its thing.
Once I set e.Handled = true, then everything was hunky dory. So if its not working for you, make sure you've done that step.

For those interested
It seems that the IDE is still breaking on exceptions and that if you click continue in the IDE it call the error handler.

Related

WPF : Dispatcher processing has been suspended, but messages are still being processed

I Have a WPF Project, When i try to Run This Code On RowLoad Event I got below Error :
private void ParentGridView_OnRowLoaded(object sender, EventArgs e)
{
try
{
if(((RadGridView)sender).Columns != null)
{
MessageBox.Show(((RadGridView)sender).Columns.Count.ToString(CultureInfo.InvariantCulture));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Error : Dispatcher processing has been suspended, but messages are still being processed.
Note That the GridView Control is Telerik RadGridView
This answer describes the same situation as yours. (It references this answer on a different website).
The dispatcher processing is suspended to avoid reentrancy problems when updating the visual tree.
If you really need to display a message box in response to your "Row Loaded" event, you need to defer the call using `Dispatcher.BeginInvoke().
So, replace:
MessageBox.Show(((RadGridView)sender).Columns.Count.ToString(CultureInfo.InvariantCulture));
with:
var msg = ((RadGridView)sender).Columns.Count.ToString(CultureInfo.InvariantCulture);
Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(msg)));
If this code is in a WPF object, then the Dispatcher property is available. Otherwise, you need to get it from somewhere else.

Duplex channel callback calls method that throws exception. Where does the execption go?

And how can I present it to the user?
This post : WCF Duplex: How to handle thrown exception in duplex Callback is very close to my scenario. And this post is useful for helping me re-establish the connection when the channel is faulted.
I have a Publishing application Pub, and a subscribing WPF application Sub. The Pub sends a message and the Sub has subscribed for a callback using a duplex channel.
Sub.ViewModel.ReactToChange(sender, e) tries to read some data, but is unable to and throws an exception.
DispatcherUnhandledException doesn't catch it (I didn't really expect it to.)
AppDomain.CurrentDomain.UnhandledException doesn't catch it (that does surprise me)
The end result is I have an application that is still running, and no exception message is shown to the user so they can correct the problem. Is there a way I can show that exception to the user?
This is a bit tricky, but the only way I've found. I hope this helps others.
The idea is to not let an exception get thrown, but instead create an UnhendledExceptionEventArg and pass it up to your UI layer. Here is some example code:
public class BuggySubscriber : IDisposable
{
public BuggySubscriber(string dataSourceName)
{
SyncContext = SynchronizationContext.Current;
Subscriber = new MockSubscriber(dataSourceName);
Subscriber.Refreshed += OnDataChanged;
}
public SynchronizationContext SyncContext { get; set; }
public event EventHandler<UnhandledExceptionEventArgs> ExceptionOccurred;
// Bouncing Exception Step 3
private void OnExceptionOccured(Exception ex)
{
var callback = new SendOrPostCallback(delegate
{
var handler = ExceptionOccurred;
if (!ReferenceEquals(handler, null))
handler(this, new UnhandledExceptionEventArgs(ex, true));
});
SyncContext.Post(callback, null);
}
void OnDataChanged(object sender, ServiceModel.DataChanged.DataChangedEventArgs e)
{
// Bouncing Exception Step 1 & 2
OnExceptionOccured(new NotImplementedException());
}
So this is the "Sub" code. In the WPF application I add the following when the app starts:
protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
BuggySubscriber.ExceptionOccurred += Sub_ExceptionOccurred;
...
}
// Bouncing Exception Step 5
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
if (!ReferenceEquals(exception, null))
ShowErrorMessage(exception);
}
// Bouncing Exception Step 4
void Sub_ExceptionOccurred(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
if (!ReferenceEquals(exception, null))
throw exception;
}
So now let's try to follow the bouncing exception.
In real life, the subscriber was notified and an exception occurs and is caught. (In my sample, I don't show that.)
Then the OnExceptionOccurred(Exception ex) is called.
That then creates the SendOrPostCallback using the ExceptionOccurred event and then does a Post to the current SynchronizationContext.
The WPF application that registered for the ExceptionOccurred (Now if you like, you could handle the exception message here... I chose to use two paths for exceptions rather than three.) It casts and throws the Exception.
Now the CurrentDomain_UnhandledException processes it and shows an error message to the user (right before it exits).
I'm sure there are many variations on this, but this does show some of the trickier code that I could not find in one place.
NOTE: This does not solve any channel problems. If you have an exception you can recover from you will still need to reestablish the channel since it will be faulted or closed.

WPF - Catch exceptions in code executed by SimpleMVVM messagebus

I'm building a WPF application using the SimpleMVVM framework and I'm having trouble catching exceptions. I use the MessageBus of SimpleMVVM to send a message to another viewmodel. This all works fine, but I noticed that exceptions raised in the code executed by the messagebus get suppressed. Here's what I've got so far:
My MainWindow contains a button that fires a TempCommand on the MainWindowViewModel. This command in turn calls the Test method (shown below), which sends out a notification message using the MessageBus of SimpleMVVM.
private void Temp()
{
SendMessage("Temp", new NotificationEventArgs());
}
My MainWindow also contains a Frame with content. The ViewModel of this content, CustomerViewModel, has registered to receive these notifications in its constructor:
public CustomerDetailsViewModel(ICustomerServiceAgent agent)
{
RegisterToReceiveMessages("Temp", Temp);
}
Where the Temp method simply throws an exception:
private void Temp(object sender, NotificationEventArgs args)
{
throw new NotImplementedException("Somewhere, something horrible happened");
}
When I debug the application, I clearly see the Temp method being called and the exception being raised. But for some reason, that's all. The application is unaffected and my exception trapping code is unaware of the exception.
I trap exceptions in two ways. The first is by handling the event on the Dispatcher:
<Application x:Class="MyApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
DispatcherUnhandledException="App_DispatcherUnhandledException">
Where the code-behind looks like:
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
Log("Exception: " + e.Exception.Message);
e.Handled = true;
}
public static void Log(string message)
{
File.AppendAllText(#"D:\Temp\log.txt", "[" + DateTime.Now.ToString("F") + "] [" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "] " + message + Environment.NewLine);
}
This code catches some exceptions, but not all. I found out that WPF suppresses databinding exceptions by default. Because my ViewModels are bounded through the DataContext property on my view, I thought this was the problem. I found this article, which defines a TraceListener that uses the PresentationTraceSources class. Databinding exceptions now get caught, but... Not the exceptions thrown in the code executed through the MessageBus.
I've created a solution demonstrating this behavior, it can be downloaded here.
And this is where I'm stuck. What am I missing? How do I catch these exceptions?
Big thanks in advance.
JP
I think it is a bug or problem with the implementation of the MessageBus in SimpleMVVM.
Cause multiple subscribers can subscribe to a token, the current implementation ensures that each subscribed method gets called even when one registered method throws an exception. In this case the exception is catched and written out to the Console.
The method that is responsible to call a subscribed method is SafeNotify
private void SafeNotify(Action method, bool post) {
try {
// Fire the event on the UI thread
if (post){
if (Dispatcher.CheckAccess()){
method();
}
else{
Dispatcher.BeginInvoke(method);
}
}
// Fire event on a ThreadPool thread
else{
ThreadPool.QueueUserWorkItem(o => method(), null);
}
}
catch (Exception ex){
// If there's an exception write it to the Output window
Debug.WriteLine(ex.ToString());
}
}
When the method call gets queued in the ThreadPool, you have no chance to handle the thrown exception. See also this post for further information.
The only option you have is to ensure that the code of your own registered methods is always surrounded by a try-catch-block.

Unhandled Exception Still Crashes Application After Being Caught

I have a WPF application that consists of multiple projects that have forms, classes, base classes, etc..
Because of the large code base I want to make sure if an exception does happen I can catch it, notify the user and let the application continue without crashing. I understand the pros and cons to doing this.
In the App.xaml.cs of the application I have:
private void OnApplicationStartup(object sender, StartupEventArgs e)
{
Application.Current.DispatcherUnhandledException += CurrentOnDispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
Dispatcher.UnhandledException += DispatcherOnUnhandledException;
UI.Views.Windows.MainWindow.Show();
}
private void DispatcherOnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs dispatcherUnhandledExceptionEventArgs)
{
MessageBox.Show("TEST 3");
}
private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
MessageBox.Show("TEST 2");
}
private void CurrentOnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs dispatcherUnhandledExceptionEventArgs)
{
MessageBox.Show("TEST 1");
}
If an exception happens anywhere those messages boxes are shown which is great, the problem is right after it shows the message the application still crashes. If I run the application in debug, Visual Studio will jump to the place were the exception happened and if I continue it will then go to the message box.
I think the problem has something to do with that but I am not sure. Is there a way to catch the exception like I am above but at the same time not have the application crash after?
Thank You
EDIT
The exceptions that get through to the UnhandledException section will be things like NullReference, NotSupported or Database Exceptions for the most park. If a "serious" exception gets cought like Stack Overflow I will simple notify the user and kill the app. I still need to find a way to stop the app from crashing on non serious exceptions though.
I think you need to set
dispatcherUnhandledExceptionEventArgs.Handled = true;
What kind of exception is your application catching? Using UnhandledException for exceptions that change state will not work unless you are setting HandleProcessCorruptedStateExceptionsAttribute attribute.
From MSDN documentation:
AppDomain.UnhandledException Event
Starting with the .NET Framework 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute.
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

Why the form load can't catch exception?

Is this a bug in Winforms? (tested on both VS2008 and VS2010)
private void Form1_Load(object sender, EventArgs e)
{
throw new Exception("Hey");
}
I don't receive any error in that code, awhile ago, I'm trying to formulate a solution for this question Parse a number from a string with non-digits in between
And I do this code in Form1_Load:
private void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("X");
string s = "12ACD";
string t = s.ToCharArray().TakeWhile(c => char.IsDigit(c)).ToArray().ToString();
MessageBox.Show("Y");
int n = int.Parse(t);
MessageBox.Show(n.ToString());
}
I wonder why it didn't show the number. Then on moving the code to button1_Click...
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("X");
string s = "12ACD";
string t = s.ToCharArray().TakeWhile(c => char.IsDigit(c)).ToArray().ToString();
MessageBox.Show("Y");
int n = int.Parse(t);
MessageBox.Show(n.ToString());
}
...then I noticed that there's an error: Input string was not in a correct format.
Why Form1_Load didn't catch any exception, why it silently fail? The code just exit out of form1_load at string t = s.ToCharArray().TakeWhile...
Rewrite, I've since figured out where it comes from. Windows misbehaves when an exception is raised in a 32-bit process when it runs on a 64-bit version of Windows 7. It swallows any exception raised by code that runs in response to a Windows message that's triggered by the 64-bit windows manager. Like WM_SHOWWINDOW, the message that causes the Load event to get raised.
The debugger plays a role because when it is active, normal exception trapping in a Winforms app is turned off to allow the debugger to stop on an exception. That doesn't happen in this scenario because Windows 7 swallows the exception first, preventing the debugger from seeing it.
I've written about this problem more extensively in this answer, along with possible workarounds.
See this: The case of the disappearing OnLoad exception. It's by-design (though by-extremely-stupid-design, IMO). Your exception is hitting a kernel-mode boundary during the unwinding of the stack. If you can, switch to some other event, or don't let exceptions escape; this doesn't help if you're expecting your debugger to automatically break on an un-handled exception in OnLoad.
If you care, I wrote a bit more in this answer.
The WinForms framework classes won't automatically catch any exceptions for you. That isn't a bug, it's by design - what would they do with the exception?
You have to have your own try/catch block in any event or alternatively handle the Application.ThreadException event. That event can be helpful for some generic handling code like logging the exception or displaying an error dialog, but obviously it can't do anything specific to any individual event or exception type.

Resources