So here is the story so far, I have this worker thingy which uses an AppDomain to perform some task. The domain is expensive to setup and teardown. So I create a cache per-thread of WeakReference objects to the worker thingy like so:
class Worker
{
[ThreadStatic]
static Dictionary<string, WeakReference> _workers;
public static Worker Fetch( ... ) { you get the idea }
private AppDomain _domain;
public Worker(...)
{
_domain = AppDomain.Create( ... );
}
~Worker()
{
AppDomain.Unload(_domain);
}
// bla bla bla
}
The problem I'm having is that seems to always throw an exception in the call to AppDomain.Unload when GC collects:
System.CannotUnloadAppDomainException: Error while unloading appdomain. (Exception from HRESULT: 0x80131015)"
So I'm thinking that's wierd, I know I don't have anything 'running' in that domain... Whats the deal? A bit of digging and trial and error I came up with this:
~Worker()
{
new Action<AppDomain>(AppDomain.Unload)
.BeginInvoke(_domain, null, null);
}
So my Questions are:
AppDomains are unloaded by a separate CLR thread. That thread cannot run while the finalizer thread is running. You're getting the exception because the CLR notices that the unload thread isn't making progress. It never gets going because the finalizer thread is blocked on the Unload call.
Deadlock.
Your workaround indeed solves that deadlock. Doing the unloading explicitly instead of relying on a finalizer is the better approach here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With