2

I have a WPF bootstrapper application: it loads my application UI from a separate assembly into another AppDomain then shows the main window. So the application UI runs from this subdomain.

The question: How to handle exceptions in the main domain thrown from the subdomain?

Why? Because my goal is to implement an application updater: when the client realizes that there is a new version is available it would throw some SystemException with a specific message.

I want the host domain to handle this specific exception: unload the subdomain, download the latest assembly version from the internet and recreate the subdomain by reloading the most up-to-date DLLs.

The problem: It seem to me that an unhandled exception in any AppDomain causes the whole thread to terminate. I found some blog post stating that one should turn on the legacyUnhandledExceptionPolicy to switch back to the .NET 1.0/1.1 legacy mode exception handling, but I'm not sure that I want to use this legacy stuff in my application.

Is there any other way to properly handle exception in other AppDomains?

Zsolt
  • 3,263
  • 3
  • 33
  • 48
  • 1
    Why use an exception? Why not just have your bootstrapper supply some callback that the app can call? – GazTheDestroyer Jul 08 '15 at 10:58
  • Do not use exceptions for control flow: http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why. Use some form of IPC instead: http://stackoverflow.com/questions/56121/ipc-mechanisms-in-c-sharp-usage-and-best-practices. – Polyfun Jul 08 '15 at 11:15
  • "that one should turn on the legacyUnhandledExceptionPolicy to switch back", no, one *should* not turn it on. It's a last resort possibility. Don't lock yourself in to the past. – usr Jul 08 '15 at 12:55
  • @usr: I agree, that's why I'm asking about another alternative. While I agree that sometimes misusing exceptions for control flow is hacky, I feel that IPC would be an overkill in my situation. I found a compromise solution: throwing a specific exception in the subdomain, handling the uncaught exception **in the same AppDomain** then firing an event to which event the parent domain subscribes and unloads the application and performs the client update. – Zsolt Jul 08 '15 at 13:41
  • 1
    Communication across app domain boundaries is very easy to do with Remoting. Can't you call into the other app domain, ask it to load the plugin or whatever and receive a return value (or an exception) back? Just a normal method call. – usr Jul 08 '15 at 13:56

2 Answers2

1

The general approach to handle custom exception 'E' caused in AppDomain-A is to have this exception defined in an assembly that is registered in GAC. So, AppDomain-A references this common assembly and AppDomain-B (observer) references this assembly.

This is because the Exception class is [Serializable] and will be passed by value over the domain boundary. Once you get the blob through the boundary, CLR will try to deserialize it. So CLR must be able to find appropriate type for deserialization. So, deserialization will lookup for the exception type according to standard rule.

There could be of course another solutions with type resolution behavior changes diving deep serialization/deserialization mechanisms.

In case if you want to learn more, just read Jeffry's book chapter about the serialization mechanisms and versioning.

PavPS
  • 76
  • 4
-1

If the appdomain is running on another thread use the AppDomain.UnhandledException event handler to handle uncaught exceptions in your new appdomain

newAppDomain.UnhandledException += new UnhandledExceptionEventHandler(ErrorHandler);

public void ErrorHandler(object sender, UnhandledExceptionEventArgs args) 
{
    Exception e = (Exception) args.ExceptionObject;
    // handle here
}

A different approach is to unload the appdomain using AppDomain.Unload, the assembly in the appdomain should handle AppDomain.DomainUnload event to close down gracefully. You can then spawn a new appdomain and start again.

This is assuming you are running the new app domain on a seperate thread, otherwise you will need to handle the exception around the calling code from the parent, becuase an unhandled exception on the main thread will abort the process.

BhavO
  • 2,406
  • 1
  • 11
  • 13