How do I cleanup .NET stuff when a C++/CLI DLL unloads?
I'm new to C++/CLI, so please bear with me...
I'm working on a mixed C++/CLI DLL, which should act as a bridge between a Win32 process and a .NET assembly. In the DLL, I need some .NET stuff to be present during the lifespan of the DLL. Initializing is no开发者_Python百科t that big a problem, but I couldn't figure out when can I safely cleanup the .NET stuff. The usual C++ facilities (DLL_PROCESS_DETACH, global variables and static locals d'tors) all seem to be called after the CLR has gone away.
So, what is the way to get notified the DLL is about to detach from the CLR, so I can release the .NET references I hold?
If you need to take care of AppDomain unloads, use the AppDomain.DomainUnload event to do your cleanup.
As STW says, libraries with managed code can never be detached from an AppDomain, the only way to detach it from your process is to unload the AppDomain.
If you aren't managing AppDomains, just leak the managed resource (and properly flush unmanaged resources during process detach). Better yet, design it as crash-only software so that no cleanup is required.
Well, answering my own question seems awkward, but this wasn't suggested by anyone else, and it is what I was looking for... so:
turns out Microsoft offers an exotic variation of onexit, called _onexit_m, which should be used in mixed-mode DLLs. When using _onexit_m to register a (managed) callback function, that function will be called when the DLL is about to be unloaded, but before the CLR has been shut down. It is similar to AppDomain.DomainUnload, suggested by Ben Voigt, but for some reason I couldn't get DomainUnload to work, and _onexit_m is simpler to use IMHO.
This might not apply to the C++ side of .NET, but to my knowledge the only way to get the CLR to release a loaded assembly is to dispose of the AppDomain; and unless you've engineered in manual AppDomain management you likely only have the initial AppDomain--making disposal the equivalent of killing your application.
.NET Dll should be treated as set of separate ref classes. Every instance of ref class has its own lifetime, and resource management is done relatively to the class instance lifetime. Properly implemented Dispose pattern solves all resource management problems.
Every C++/CLI class, which has some native resources, or disposable class members, should have destructor and optional finalizer. Specifically, .NET references are released in the class destructor, which is mapped to C# Dispose method.
精彩评论