开发者

Catching Exceptions in WPF at the FrameWork Level

开发者 https://www.devze.com 2023-02-02 19:54 出处:网络
I\'m developing a light-weight WPF MVVM framework, and would like to be able to catch unhandled exceptions, and ideally recover from them.

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 DispatcherUnhandledExceptionEventHandle开发者_JAVA百科r(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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号