I was recently reading the "remarks" section for the AppDomain.Unload() method @ http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemAppDomainClassUnloadTopic.asp. I was doing a review of the documenation available to determine if we needed more around the CannotUnloadAppDomainException exception. I decided that we were in an OK spot for the most part, but that I would post a little more information on this exception for the small percentage of .NET programmers out there who need it. At least, I certainly hope that most .NET programmers don't need this information ;)
Note: Please mail me if this information proves particularly useful for you -- I'd like to better understand your scenario.
Upon calling the AppDomain.Unload() method, the CLR will request that all threads in the unloading domain abort. Threads do not abort instantly, so getting n threads to abort will take some time. As a result, the CLR checks after 10ms* to determine if there are any threads still running. If there are not any threads still running, then the CLR will proceed with domain shutdown. If there are threads still running, then the CLR repeats this process -- wait 10ms and check -- up to 1000* times. In the general case, it is very unlikely to need to repeat this process 1000 times (or anything close to it); eventually, all threads will be aborted and domain shutdown will occur. The purpose of this repeating "wait and see" behaviour is to avoid a deadlock due to a thread that will not abort for some reason.
If the 1000th check fails, meaning that threads are still running (not yet aborted), the CLR will throw a "CannotUnloadAppDomainException" exception. If the application, after the exception has been thrown, can do something to prevent this situation from occuring again (i.e. cleanup or manually aborting threads) then the application should perform that cleanup and call AppDomain.Unload() again. It is not expected, however, that the app should attempt to try repeat this process -- catching the "CannotUnloadAppdomainException" exception and calling AppDomain.Unload() -- an indeterminant number of times until it "works". The best approach is to remove the case where the exception is thrown at all, which means ensuring that all threads in a domain can be aborted in a timely manner. If the application, after the exception has been thrown, cannot do anything to prevent this situation from occuring again, it should not call AppDomain.Unload() again, but terminate the application or leak the domain.
* please consider these numbers (10ms and 1000 times) as implementation details. You absolutely should not take a dependency on them, for two reasons: (A) they are subject to change in a later release w/o notice, and (B) the number of running threads, processes and CPUs (+ multi-core) can very significantly change the time it takes to hit the 1000th iteration of the check due to the amount of CPU time that the unload check is given.
Powered by: newtelligence dasBlog 2.3.9074.18820
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2010, Rich Lander
E-mail