I saw some “interesting” behavior in a plugin system I had written (same culprit I have seen before file locks) was doing some more research and came accross this wonderful blog http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx
An Abort is performed on all threads that have stack in an AppDomain that is being unloaded. Since we are throwing away the AppDomain anyway, we can often tolerate surprising execution of threads at fairly arbitrary spots in their execution. Even if this leaves managed locks unreleased and AppDomain statics in an inconsistent state, we’re throwing away all that state as part of the unload anyway. This situation isn’t as robust as we would like it to be. So we’re investing a lot of effort into improving our behavior as part of getting “squeaky clean” for highly available execution inside SQL Server in our next release.
Unfortunately, this is not really the case. In some previous posts http://geekswithblogs.net/gyoung/archive/2005/12/23/64025.aspx I looked at some of the evil things thread.abort can cause in combination with unmanaged resources. The big problem here with doing it on an appdomain unload is that the resources are not scoped to the appdomain; these unmanaged resources are bound to the process (I believe one could have similar problems with say a mutex or another unmanaged item).
I don't think there is any possible solution to this problem but it basically puts you into a situation where loading/unloading app domains within your process forces you into a non-deterministic state (something I try to avoid). I am quite sure after my previous looks into how things are managed in the framework that there are numerous places where an unmanaged resource is acquired and that there is a period of time before a managed wrapper is placed around it to protect it.
Perhaps one of the wonderful people reading this can come up with a solution to this problem in the current framework because I am completely stumped. As a long term solution it would be wonderful if I could some how tell the CLR that this code is dangerous and to not interupt during it (of course it would also involve making the entire framework know about this but that should only take a team of summer interns a few weeks). Although now that I think about it, I am not quite sure that this is even feasable.
Perhaps the best solution is a coding standard to force a shutdown through a method in the other appdomain prior to unloading it.