I'm trying to use a legacy C++ DLL in a .net application, and I'm
running into problems with the application not shutting down if any of
the methods on the DLL are invoked. I've tried accessing the DLL
through both p/invoke, and directly through managed C++, and the
results are the same. I start a windows forms application, call any
method on the DLL (all of which seem to work as expected), and then
close the main application form. This should exit the application, and
does if there are no DLL calls. Otherwise, the process simply does not
die (I have to manually kill it in the task manager). Is there
something else that I need to do with interop to make sure that the Dll
actually unloads?
cmbardon@engmail.uwaterloo.ca - 14 Sep 2005 14:39 GMT
It appears that I've solved my own problem, but I'm not sure why the
solution was required. The DLL in question had a global object that
controlled access to a COM resource. The class looked something like
this:
class CComWrapper
{
public:
DWORD Init(BOOL fMultiThreaded)
{
HRESULT hRes = 0;
if(fMultiThreaded)
{
hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
}
m_obj.Init();
return hRes;
}
~CComWrapper() { m_obj.DeInit(); };
CComObj m_obj;
};
CComWrapper ComObj; //creates the global object
In one of the DLL methods, the CComWrapper object was initialized by
calling the init() method. The COM object (CComObj) did its own
initialization in its Init() method, which seems to be where the
problem occurred. In previous C++ apps, the object's destructor would
(presumably) run, and the COM object would be allowed to clean up any
outstanding resources/threads etc. In the interop case however, it
looks like this method never ran. My solution was to create a DLL
method that forced the COM object's DeInit() method to be called: once
I did this, my .net application shut down as expected.
What I'd like to know is if anyone can tell me why the .net application
didn't shut down without this call. I have two ideas:
-The COM objects DeInit() method (called in the wrapper's destructor)
has never actually been called, and in the unmanaged world this just
constituted a leak. In .net however, the CLR is keeping track of
threads created by unmanaged DLLs, and it isn't allowing an application
to close before killing all of its threads.
-The CLR is keeping the DLL loaded until the appliation has exited, but
the application is waiting for the DLL to unload before exiting,
causing a deadlock (or something similar).
Am I even close? I'd really like to understand what's going on here.
Oh, and for the record, I had nothing to do with the way that the
legacy DLL was authored, and I know from looking at it that it could be
improved. A complete redesign isn't really an option here, so I'm
stuck with what's there.
Thanks for your replies!