Use AppDomain.UnhandledException in modular forms application
I am currently developing a .NET application completely modular, in which:
- There is the host applicaiton that loads module DDLs. The module DDLs have forms that can be opened several times.
- You can unload the application domain. This will cause all the opened forms of the module to be closed.
What I want to do is to, when an unhandled exception happens in the module, the application should unload the DDL of that module and prevent the Host to crash.
I tried to use the AppDomain.UnhandledException Event, which has a handler assigned to it right after the creation of the AppDomain as follows:
// Creates the ApplicationDomain
this._applicationDomain = AppDomain.CreateDomain(this.AppDomainName);
this._applicationDomain.UnhandledException += new UnhandledExceptionEventHandler(_applicationDomain_UnhandledException);
The problem is: that the handler is never called. Microsoft says here that
For example, suppose a thread starts in application domain "AD1", calls a method in application domain "AD2", and from there calls a method in application domain "AD3", where it throws an exception. The first application domain in which the UnhandledException event can be raised is "AD1". If that application domain is not the default application domain, the event can also be raised in the default application domain.
Even after I assign the handler, the exception still goes to
Application.Run(new HostForm());
I suppose that, if I created a new message loop for each module's form it would work, because then the thread in which the form would be running would be a separated thread, but it seems to be a stupid solution.
Another idea I had was to use than the AppDomain.UnhandledException Event of the default application domain, but how can I then:
- Discover the AppDomain of origin开发者_如何学Python and therefore the module to unload?
- Prevent the Application to die? (I tried doing this and the e.IsTerminating comes with true value and the exception is still caught in the
Anyone? Please, I really need it.
There's a reasonably good explanation (with supporting links) about why the AppDomain.CurrentDomain.UnhandledException handler doesn't suppress unhandled exceptions here. The MSDN article you linked to also describes this behaviour just below the part you quoted.
In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurs in a thread other than the main application thread is caught by the runtime and therefore does not cause the application to terminate. Thus, it is possible for the UnhandledException event to be raised without the application terminating. Starting with the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug.
So even if you could get the event to fire, it isn't likely to satisfy your requirement that the application not be terminated shortly afterwards. The UnhandledException handler is really only there to give you one last chance to log important information before the application is terminated.
The most resilient applications (Google Chrome for instance) will use full process isolation to ensure anything that goes wrong in a plugin tears down the external plugin host, not the main application. I've used this mechanism myself to create an application similar to the one you describe, and even went to the extent of creating sandboxed AppDomain's inside each external plugin host to ensure plugins couldn't delete critical files if the main application was elevated.
There's a really good article here that describes isolation techniques in detail and reiterates that the AppDomain plugin system isn't the best option due to the UnhandledException problem. If you're serious about a fault tolerant plugin architecture I'd recommend implementing full process isolation as described in that last article.
精彩评论