Where do I release my object's expensive resources, if not in the destructor?
-
I have an object that creates an expensive COM object as soon as my object's Constructor is called. This COM object is treated as a private field in my object. My object is then responsible releasing that COM object. Not releasing it is expensive and problematic. So I put the release code for the COM object in my object's destructor, assuming my object's destructor would be called as soon as my object was set to NULL or went out of scope. However, this is not the case. My object's destructor is not called until the garbage collector runs. This is a problem. I need my object to release the COM object as soon as it's not needed anymore. If I don't, there are problems with the COM server application - ie, it won't close, etc. How can I insure that my object releases the COM object as soon as my object is set to null, or goes out of scope? Where do I put the COM release code?
-
I have an object that creates an expensive COM object as soon as my object's Constructor is called. This COM object is treated as a private field in my object. My object is then responsible releasing that COM object. Not releasing it is expensive and problematic. So I put the release code for the COM object in my object's destructor, assuming my object's destructor would be called as soon as my object was set to NULL or went out of scope. However, this is not the case. My object's destructor is not called until the garbage collector runs. This is a problem. I need my object to release the COM object as soon as it's not needed anymore. If I don't, there are problems with the COM server application - ie, it won't close, etc. How can I insure that my object releases the COM object as soon as my object is set to null, or goes out of scope? Where do I put the COM release code?
You can't. You can use the dispose/finalise mechanism to let your users call Dispose to close it, or for finalise to do it when the object is GC, if dispose was not called. Welcome to garbage collection.
Christian Graus No longer a Microsoft MVP, but still happy to answer your questions.
-
You can't. You can use the dispose/finalise mechanism to let your users call Dispose to close it, or for finalise to do it when the object is GC, if dispose was not called. Welcome to garbage collection.
Christian Graus No longer a Microsoft MVP, but still happy to answer your questions.
-
You can't. You can use the dispose/finalise mechanism to let your users call Dispose to close it, or for finalise to do it when the object is GC, if dispose was not called. Welcome to garbage collection.
Christian Graus No longer a Microsoft MVP, but still happy to answer your questions.
-
This suggests, then, that I shouldn't even bother putting the COM release code in my destructor, right? The COM object will be released anyway when my object gets GC'ed, correct?
Any object that uses any unmanaged resources should implement the IDisposable interface, so that the resources can be released in a controlled manner. You have no control over when the object is garbage collected, and there is actually no guarantee that the object is ever garbage collected.
Despite everything, the person most likely to be fooling you next is yourself.
-
Any object that uses any unmanaged resources should implement the IDisposable interface, so that the resources can be released in a controlled manner. You have no control over when the object is garbage collected, and there is actually no guarantee that the object is ever garbage collected.
Despite everything, the person most likely to be fooling you next is yourself.
-
This suggests, then, that I shouldn't even bother putting the COM release code in my destructor, right? The COM object will be released anyway when my object gets GC'ed, correct?
Wrong. Non-managed resources, need to be dealt with in your code. The idea is you impliment IDisposable, so the user can call Dispose to force cleanup, but write code that does the cleanup if Dispose has not been called.
Christian Graus No longer a Microsoft MVP, but still happy to answer your questions.
-
I have an object that creates an expensive COM object as soon as my object's Constructor is called. This COM object is treated as a private field in my object. My object is then responsible releasing that COM object. Not releasing it is expensive and problematic. So I put the release code for the COM object in my object's destructor, assuming my object's destructor would be called as soon as my object was set to NULL or went out of scope. However, this is not the case. My object's destructor is not called until the garbage collector runs. This is a problem. I need my object to release the COM object as soon as it's not needed anymore. If I don't, there are problems with the COM server application - ie, it won't close, etc. How can I insure that my object releases the COM object as soon as my object is set to null, or goes out of scope? Where do I put the COM release code?
After nulling all references to the COM object, you can call GC.Collect () to force garbage collection. See ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref2/html/O_T_System_GC_Collect.htm
-
I have this problem with Enterprise Architect (modelling software from Sparx). The program exposes a COM automation interface for add ins, and when you write an add in with C# it can happen that the application refuses to close because your add in's COM reference which has not been garbage collected. Sparx recommends to call GC.Collect() and GC.WaitForPendingFinalizers(). Maybe you can do this in your Dispose() method after releasing the COM reference. It's often said one should not call the GC methods for performance reasons, but when it's about releasing a big COM object they're probably justified.
-
After nulling all references to the COM object, you can call GC.Collect () to force garbage collection. See ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref2/html/O_T_System_GC_Collect.htm
-
yes, that's how I release the COM object in my destructor. But that's not the question here. The point is, unless my client (who created my object) calls Garbage Collection explicitly, my destructor won't be called in a timely fashion.
Maybe you could figure out when the client is done with the object. Is there a method in the object that is called as a final operation? If so, you could invoke garbage collection at that point. Or (depending on the particular usage pattern) you might be able to detect when the client is X seconds away from not needing the object, and set a timer to force garbage collection after X+1 seconds.
-
After nulling all references to the COM object, you can call GC.Collect () to force garbage collection. See ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref2/html/O_T_System_GC_Collect.htm
Calling
GC.Collect()
directly is generally a bad idea.Scott Dorman
Microsoft® MVP - Visual C# | MCPD President - Tampa Bay IASA [Blog][Articles][Forum Guidelines]
Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
-
This suggests, then, that I shouldn't even bother putting the COM release code in my destructor, right? The COM object will be released anyway when my object gets GC'ed, correct?
As Guffa pointed out, the GC has no knowledge of how to release unmanaged memory, which includes COM objects. It expects that your managed class will provide the necessary logic to free those resources during GC by implementing
IDisposable
.Scott Dorman
Microsoft® MVP - Visual C# | MCPD President - Tampa Bay IASA [Blog][Articles][Forum Guidelines]
Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
-
yes, that's how I release the COM object in my destructor. But that's not the question here. The point is, unless my client (who created my object) calls Garbage Collection explicitly, my destructor won't be called in a timely fashion.
JoeRip wrote:
The point is, unless my client (who created my object) calls Garbage Collection explicitly, my destructor won't be called in a timely fashion.
That's one of the drawbacks to a garbage collected runtime. The idea is that you implement the
IDispsoable
interface (actually, the Dispose pattern[^]) which tells the GC how to release your unmanaged memory and signals to the caller (client) that they should callDispose()
when they are done using your object. If you need a stronger assurance that your resources get cleaned up then you can implement a finalizer (see the above reference article for issues/concerns about implementing finalizers) and if you absolutely need to guarantee the finalizer gets called you need use a "critical finalizable object" and inherit fromCriticalFinalizerObject
.Scott Dorman
Microsoft® MVP - Visual C# | MCPD President - Tampa Bay IASA [Blog][Articles][Forum Guidelines]
Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai