Releasing COM Object in Constructor Parameter - c#

I am developing a VSTO addin where now I am looking to optimize it. In my code, I does something
public class ExtraOrdinaryClass
{
public ExtraOrdinaryClass(Excel.Worksheet someGoodSheet)
{
tSheetName = someGoodSheet.Name;
tDesignSheet = someGoodSheet;
}
}
I just got to know I should release all the COM Objects, but I am searching for a proper way to release the someGoodSheet object in a proper way. I suspect if I do something like below is efficient
public class ExtraOrdinaryClass
{
public ExtraOrdinaryClass(Excel.Worksheet someGoodSheet)
{
tSheetName = someGoodSheet.Name;
tDesignSheet = someGoodSheet;
Marshal.ReleaseComObject(someGoodSheet);
someGoodSheet = null;
}
}
Can anyone help me if I am doing it effectively and tell me when parameter objects are collected by garbage collector?

I just got to know I should release all the COM Objects, but I am searching for a proper way to release the someGoodSheet object in a proper way
It is not necessary to worry about releasing COM objects because you are writing a VSTO add-in. VSTO add-in are in-process COM libraries loaded by the COM application, in this case Excel. The COM object represented by the Excel worksheet was created by Excel and so it has ownership. Attempting to manually release (via Marshal.ReleaseComObject) or reduce the reference count inordinately when you still have a managed reference to it (as in your second example), may crash Excel and/or your application.
Had you been writing a stand-alone process which say launched Excel via COM and fiddled with a few COM objects, then yes, you would need to ensure COM objects are released appropriately.
i.e. do not use this in your constructor:
Marshal.ReleaseComObject(someGoodSheet);
Because you are essentially saying to COM "I'm finished with it" and yet you are not because you still have a managed referenced to it via tDesignSheet. COM/Excel may choose to get rid of the worksheet from under you. The next time you go to access tDesignSheet you may encounter an exception.
Calling Marshal.ReleaseComObject on a parameter that is copied to a field is sort of like using a Font after you called Dispose() - both will lead to the undesirable situation where an obliterated object is accessed. (in the case of COM I assume the reference count reached 0)
Also it is not necessary to call this (because you have a reference to the same object anyway):
someGoodSheet = null;
Your original code (shown below) is fine:
public class ExtraOrdinaryClass
{
public ExtraOrdinaryClass(Excel.Worksheet someGoodSheet)
{
tSheetName = someGoodSheet.Name; // you arguably don't need this (just read tDesignSheet.Name)
tDesignSheet = someGoodSheet;
}
}
and tell me when parameter objects are collected by garbage collector?
I would say that in this case the .NET parameter would not be collected because now you have an additional reference to it in tDesignSheet inside ExtraOrdinaryClass. You would either need to set tDesignSheet to null and wait for the next time the GC runs, whenever that is.
Even if the .NET object is collected, .NET I suspect is smart enough to know that the COM object may still be used by other native COM clients such as Excel itself.
So, just because your .NET now-disposed objects no longer refer to the COM object, you may find the COM object could well be still active. e.g. the worksheet is still open.

Related

Release COM when developing an Excel Addin?

I understand that I should release COM objects when using interop. Are things a bit different when developing and Add-In, Excel for example? Here is a loop I have and I was curious to know if the Marshal.ReleaseComObject is necessary?
foreach (var sheet in results.Sheets)
{
var newSheet = workbook.AddSheet();
newSheet.SetSheetTabColor(sheet.TabColor);
newSheet.SetSheetName(sheet.TabName);
newSheet.Cells.SetFont("Calibri", 8);
newSheet.FreezeRow(1);
var endRow = sheet.Data.GetUpperBound(0) + 1;
var endColumn = sheet.Data.GetUpperBound(1) + 1;
var writeRange = newSheet.SetWriteRange(1, 1, endRow, endColumn);
writeRange.Value2 = sheet.Data;
newSheet.AutoFitColumns();
newSheet.RemoveColumn(1);
Marshal.ReleaseComObject(newSheet);
}
Also, I created a library with extension methods. One example is workbook.AddSheet() AddSheet looks like this:
public static Worksheet AddSheet(this Microsoft.Office.Interop.Excel.Workbook workbook)
{
var sheets = workbook.Sheets;
return sheets.Add(After: sheets[sheets.Count]);
}
Since I am accessing sheets from workbook.Sheets, do I have to release of this object? If so where since I am returning a Worksheet? I can't release before I return?
This may be a dumb question, but if the Marshal.ReleaseComObject was not necessary in the foreach scope, does it hurt even if it is still there?
Marshal.ReleaseComObject is used only if you need to control the lifetime of an COM object in timely manner, or in specific order. For casual usage of COM objects i would not advice you to use this method at all.
Check here
This method is used to explicitly control the lifetime of a COM object
used from managed code. You should use this method to free the
underlying COM object that holds references to resources in a timely
manner or when objects must be freed in a specific order.
About your second question
Since I am accessing sheets from workbook.Sheets, do I have to release
of this object? If so where since I am returning a Worksheet? I can't
release before I return?
The COM implementation in .NET is using reference counting mechanism to detect if object is used or not, so NO you don't have to release anything explicitly. The framework is resposible for this.
NOTE:
Use the approriate .Close(for Workbook), .Quit(for Application) methods for proper release of resurces. When you use .Quit() over the application object you will close the excel process in windows (so this will release all resource), and .Close() over a Workbook to release file locks .. etc over specific excel file.

Influencing the GC order (keeping an object alive)

Following Situation: I've got a singleton-class which is loading a C-DLL internally (let's call it Foo), and also constructs elements which are accessing the same DLL (also in the d'tor) - it's name shall be Bar.
The problem now is: When I close the Application, the GC sometimes destroys Foo before all the created Bar instances are destroyed. The result is undesireable: Foo is a nice class and cleans up after itself, including closing the DLL. Bar needs to access a DLL function on closing - leading to an access violation.
So the Question is: how to resolve this Issue? My initial approach was: Since Foo is creating all Bar instances, just put every created Bar instance into a List (which is a member of Foo) to create some references, the idea obviously: The GC might destroy all the references before destroying the object holding it. Unfortunately, this isn't the case (probably because of possible circular references) Maybe there is some strong reference which can force this behaviour.
So... any ideas?
Addendum:
The idea of using IDisposeable seems great. One particular issue comes to mind: I don't want to encapsule the created Bar object in try or using blocks (since I want to have it available for multiple independent functions).
So my approach would be to still keep track of the created Bar objects inside the Foo singleton and just call Dispose for each Bar on Foo destructor, as well as calling it individually on each Bar destructor. In my particular implementation, this seems to be fine, as I'm making sure that the functionality is only called once (so either Bar is destructed first then it's ok since Foo is still up, or Bar is destructed last, then the critical functionality isn't going to be called again).
Still...this approach doesn't seem very clean, let's see following example:
Bar bar = null;
void Func1()
{
if(bar == null) bar = Foo.Instance.CreateBar();
bar.DoSomething();
}
void Func2()
{
if(bar == null) bar = Foo.Instance.CreateBar();
bar.Dispose();
}
If I'm calling only Func1 this fine. However...calling Func1 after calling Func2 might cause issues (since DoSomething requires the object not to be disposed). Granted: I can still add some security checks, but somehow this doesn't seem clean to me.
Are there any better practises?
Maybe one additional point regarding the usecase: This is all part of a library (a DLL wrapper actually) where I've got a Singleton (which holds access to the DLL) which is used to create specific objects. These objects are used inside the DLL using handles. To benefit the user experience, I decided not to expose the handles towards the user but a specific class instead (which is keeping the handle internally, the usage then is more straight forward).
So instead of
uint handle = Foo.Instance.CreateObject();
Foo.Instance.DoSomething(handle);
Foo.Instance.Destroy(handle);
I have s.th. like:
Bar bar = Foo.Instance.CreateBar();
bar.DoSomething();
//I don't want the user to care about destruction, which is actually causing my initial problem
Maybe this architecture is flawed, but I honestly can't think of a better way (actually, I think this is a good architecture)
You are trying to solve a problem that the CLR refuses to tackle, strong hint that there's trouble looming on the horizon. Finalization order is non-deterministic, you can't force it either. You'll have to reference-count yourself to know when no remaining Foo or Bar objects remain. Increment it in their constructors, decrement it in their finalizers, cleanup when it reaches 0.
Note that this does mean that the clean-up code cannot be part of Foo or must be static since it might be a Bar that's the one that counts the reference count down to 0.
Watch out for "thrashing", the client code repeatedly creating a Foo and letting it die again, you'll constantly load and unload the DLL. Maybe leaving the DLL resident isn't that bad after all :) The pinvoke plumbing certainly doesn't think it is.

Disposing Custom Class : Setting NULL VS .Dispose [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Calling null on a class vs Dispose()
Just want some information regarding Disposing an Object.
I have create a Employee Class which i inherit from IDISPOSIBLE Interface. Below is the sample Code
public class Employee : IDisposable
{
private Int32 _RunID;
public Int32 RunID { get { return _RunID; } set { _RunID = value; } }
public void Dispose()
{
//Dispose(true);
}
}
Now my Question is, it a Good Coding Practice to Dispose every class we create and implementing/Inheriting it with IDisposible Interface even i have seen many other people code they directly set ObjEmployee = null; so just got confused which is good setting NULL or Implementing it With IDisposible Interface or None Of the Above ?
It depends, do you have managed resources (File handles, sockets, connections, etc....) that need to be gotten rid of along with your object? If yes then you need a Dispose() if your class contains basic types or just information you do not need to dispose and setting to null will give a hint to the GC to clear that memory.
When you set ObjEmployee = null, you only mark the object instance to be ready for the Garbage Collector, but you have no influence over when the actual clean-up would take place, and it may take a while. When you use the Dispose() method, the GC runs immediately and frees the memory the object was using.
The fundamental question, in deciding whether a class should implement IDisposable, is whether instances of that class have taken on the responsibility of seeing that other entities get cleaned up; typically those other entities will be altering their behavior on behalf of the IDisposable object and at the expense of other entities, and the IDisposable object is responsible for letting them know when they no longer need to do so.
For example, if any code, anywhere, uses the C function fopen() to open for read-write access a file which is located on a server, the server will alter its behavior by forbidding anyone else from accessing the file until it receives word that the program that opened it has no more need of it. When the program no longer needs exclusive use of the file, it can call fclose() which will in turn cause the server to be notified that the file should again be available to other applications.
If a method in a C# class calls a routine which calls fopen(), and that routine returns after putting the FILE* in a place the C# program knows about but nothing else does, that method takes on a responsibility for seeing that fclose() must somehow get called with that FILE*. The file needs to be fclosed(), and nothing else in the system has the information or impetus necessary to do so, so the responsiblity falls to that C# class.
If the C# method were to return without storing the FILE* anywhere, the file would never get closed, and nobody else, anywhere in the universe, would be able to use it unless or until the application exits. If the C# method has to exit without yielding exclusive use of the file, it must store the FILE* in a way that will ensure that someone, somewhere, will clean it up after exclusive use is no longer required. The normal pattern would be for the method to store the FILE* in a class field, and for class containing the method to implement IDisposable by copying and blanking that field, seeing if it was non-blank, and if it was non-blank, calling fclose() the stored FILE*.
The important thing to realize is that when an object is destroyed by the garbage collector, the system won't care what's in any of the object fields. It won't even look at them. What matters is whether the object has any unfulfilled responsibilities for ensuring that outside entities, which may not even be on the same machine, are informed when their services are no longer needed.

C# Collect garbage of object with memory leak

I am using a 3rd-party object I didn't create that over time consumes a lot of resources. This object shouldn't in any way contain a state, it simply performs a calculation. Despite this fact, everytime I call a specific function of this object a little more memory is consumed. A few hours later, and my program is sitting at gigabytes of allocated memory.
The object was origionaly initialized as a static member of my Program class in my command-line application. I have found that if I wrap my entire program in an class, and reinitialize it every now and again, the older (and bloated) object is unallocated by GC and a new smaller object replaces it.
My issue is this method is quite clumsy and ruins the flow of my Program.
Is there any other way you can dispose of an object? I am lead to believe GC.Collect() will only dispose unreachable code. Is there anyway I can make an object 'unreachable'?
Edit: As requested, the code:
static ILexicon lexicon = new Lexicon();
...
lexicon.LoadDataFromFile(#"lexicon.dat", null);
...
byte similarityScore(string w1, string w2, PartOfSpeech pos, SimilarityMeasure measure)
{
if (w1 == w2)
return 255;
if (pos != PartOfSpeech.Noun && pos != PartOfSpeech.Verb)
return 0;
IList<ILemma> w1_lemmas = lexicon.FindSenses(w1, pos);
IList<ILemma> w2_lemmas = lexicon.FindSenses(w2, pos);
byte result;
byte score = 0;
foreach (ILemma w1_lemma in w1_lemmas)
{
foreach (ILemma w2_lemma in w2_lemmas)
{
result = (byte) (w1_lemma.GetSimilarity(w2_lemma, measure) * 255);
if (result > score)
score = result;
}
}
return score;
}
As similarityScore is called, more memory is allocated to a private member of lexicon. It does not implement IDisposable and there are no obvious functions to clear the memory. The library is based on WordNet, and uses an algorithm to find path lengths in the hypernym tree to calculate the similarity of two words. Unless there is caching, I can't see why it would need to store any memory. What is for sure, is I can't change it. I'm almost certain there is nothing wrong with my code. I just need to dispose of lexicon when it gets too large (N.B. it takes a second or two to load the lexicon from file to memory)
If the object doesn't implement IDisposable and you want to push it out of scope you can set all references to it to null and then the force garbage collection with GC.Collect().
GC.Collect() is very expensive. If you're going to have to do this frequently, you might want to consider contacting the vendor.
Find out:
If you are using their library correctly, or is there something you're doing wrong that's causing the memory leak.
If their library is leaking memory even when used as intended, can they fix the leak?
Additional note: If the 3rd party library is native and you're having to use interop, you can use Marshal.ReleaseComObject to free unmanaged memory.
you could try calling the Dispose() method. This would make the object unusable, so you would have to instantiate another one. I assume your program is in a loop, so it can be a loop variable with the call to dispose at the bottom.
I would suggest that if you can get your hands on a memory profiler, you use it. A memory profiler will let you pause your program, click on a class, and and see a list of objects of that class. One can then click on an object and see how it was created, and the "path" to that object from a root (e.g. there's a static class foo, which holds a reference to a bar, which holds a reference to a boz, which holds a reference to a reallybigthing). Often, seeing that will make it clear what needs to be done to break the chain.
you might be able to download the source from wordnet repository and modify the code since it is an opensource.

Which Excel Interop objects to clean up myself and which to clean up by GC.Collect()

Question:
I want to ask a question in response to Mike Rosenblum's answer to this question. The question was about cleaning up Excel interop objects. Several solutions where suggested (e.g. wrappers, not using more than one dot, killing the excel process), but I liked Mike Rosenblum's solution to this problem the most (lengthy article about the topic).
What it basically says is that you don't worry too much about all the references floating around. You just keep some main ones (like ApplicationClass, Workbook and Worksheet). You first invoke garbage collection to clean up all the objects floating around and then explicitly clean up the main references you still have by calling Marshal.FinalReleaseComObject (in reverse order of importance).
Now I have two questions about this.
First: How do I determine to which objects I need to keep a reference? In Mike Rosenblum's example he only keeps Ranges, Worksheets, Workbooks and ApplicationClasses.
Second: If there are more objects, how do I determine the order of cleaning them up (i.e. the "order of importance")?
Thanks in advance.
Update 1:
It has been suggested by MattC that for the order, the only thing that is important is that the app is released last. Although in my reference the following sentence:"You should also release your named references in reverse order of importance: range objects first, then worksheets, workbooks, and then finally your Excel Application object." implies that there is more ordering.
nobugz Suggests that setting everything to null and then doing garbage collection will suffice, but that seems to contradict the following quote from Mike Rosenblum's article:"You would think, then, that you can set all your variables = Nothing and then call GC.Collect() at the end, and this does work sometimes. However, Microsoft Office applications are sensitive to the order in which the objects are released and, unfortunately, setting your variables = Nothing and then calling GC.Collect() does not guarantee the release order of the objects."
Update 2:
Some extra info:
In my own application, I do a lot of things with a chart. I am setting a lot of properties etc. As I understand, there are many places where I create new COM objects. I tried to make sure I never use double dots, and I tried to call Marshal.FinalReleaseComObject on all objects that I am finished with. I didn't use the wrapper approach because it would introduce a lot of nesting.
EXCEL.exe did not close after my app finished its work. But... it did close when I told my app to do the same work again. Of course a new EXCEL.exe opened which did not close. Now I have removed alllll the Marshal.FinalReleaseComObject calls and the app works exactly the same. The EXCEL.exe stays, until I tell my app to redo the work, but then a new EXCEL.exe starts and stays.
EDIT: Also when I tell my app to do other non-COM related work, after a while the EXCEL.exe disappears, but now no new EXCEL.exe appears.
Not sure what conclusions I can draw from this...
You should have no trouble finding possible live references in your code, they will be fields in your class(es). Or local variables in the cleanup method, that's unlikely. The list provided in the link are just objects that you most likely will store in a field. There could be others, they'll keep Excel just as alive as the Application object.
I don't think I'd recommend the jackhammer approach as advocated in the link, it just hides a potential life reference to an RCW that wraps a dead COM interface. A best you'll have a possibly permanent leak to the RCW object, at worst it crashes your program with an exception when it accidentally references the object. Bugz, to be sure, just not ones you'll easily discover. All you have to do is set your references to null, order doesn't matter, then collect.
I've had a similar problem this is what my catch and finally look like for clean up. I hope it helps.
.......
oWB._SaveAs(strCurrentDir +
strFile, XlFileFormat.xlWorkbookNormal, null, null, false, false, XlSaveAsAccessMode.xlShared, false, false, null, null);
sumsheet.Activate();
oWB.Close(null, null, null);
oXL.Workbooks.Close();
oXL.Quit();
}
catch (Exception theException)
{
theException.ToString();
}
#region COM Object Cleanup
finally
{
// Cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oRng);
//System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sumSheet);
//System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oSheet);
//oWB.Close(null, null, null);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oWB);
oXL.Quit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oXL);
}
#endregion
EDIT
If you noticed I've commented out the sumSheet + oSheet(Which are my worksheets) because it wasn't needed. This code has solid for me with no problems. I've found by rearranging the order I've gotten errors.
I think as long as application is last you can release them in any order (as long as they aren't null).
Then do a GC.Collect to finally kill the excel.exe process.

Categories

Resources