All of these questions:
Excel 2007 Hangs When Closing via .NET
How to properly clean up Excel interop objects in C#
How to properly clean up interop objects in C#
struggle with the problem that C# does not release the Excel COM objects properly after using them. There are mainly two directions of working around this issue:
Kill the Excel process when Excel is not used anymore.
Take care to explicitly assign each COM object used to a variable first and to guarantee that eventually, Marshal.ReleaseComObject is executed on each.
Some have stated that 2 is too tedious and there is always some uncertainty whether you forget to stick to this rule at some places in the code. Still 1 seems dirty and error-prone to me, also I guess that in a restricted environment trying to kill a process could raise a security error.
So I've been thinking about solving 2 by creating another proxy object model which mimics the Excel object model (for me, it would suffice to implement the objects I actually need). The principle would look as follows:
Each Excel Interop class has its proxy which wraps an object of that class.
The proxy releases the COM object in its finalizer.
The proxy mimics the interface of the Interop class.
Any methods that originally returned a COM object are changed to return a proxy instead. The other methods simply delegate the implementation to the inner COM object.
Example:
public class Application
{
private Microsoft.Office.Interop.Excel.Application innerApplication
= new Microsoft.Office.Interop.Excel.Application innerApplication();
~Application()
{
Marshal.ReleaseCOMObject(innerApplication);
innerApplication = null;
}
public Workbooks Workbooks
{
get { return new Workbooks(innerApplication.Workbooks); }
}
}
public class Workbooks
{
private Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks;
Workbooks(Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks)
{
this.innerWorkbooks = innerWorkbooks;
}
~Workbooks()
{
Marshal.ReleaseCOMObject(innerWorkbooks);
innerWorkbooks = null;
}
}
My questions to you are in particular:
Who finds this a bad idea and why?
Who finds this a gread idea? If so, why hasn't anybody implemented/published such a model yet? Is it only due to the effort, or am I missing a killing problem with that idea?
Is it impossible/bad/error-prone to do the ReleaseCOMObject in the finalizer? (I've only seen proposals to put it in a Dispose() rather than in a finalizer - why?)
If the approach makes sense, any suggestions to improve it?
Is it impossible/bad/dangerous to do the ReleaseCOMObject in the destructor? (I've only seen proposals to put it in a Dispose() rather than in a destructor - why?)
It is recommended not to put your clean up code in the finalizer because unlike the destructor in C++ it is not called deterministically. It might be called shortly after the object goes out of scope. It might take an hour. It might never be called. In general if you want to dispose unmanaged objects you should use the IDisposable pattern and not the finalizer.
This solution that you linked to attempts to work around that problem by explicitly calling the garbage collector and waiting for the finalizers to complete. This is really not recommended in general but for this particular situation some people consider it to be an acceptable solution due to the difficulty of keeping track of all the temporary unmanaged objects that get created. But explicitly cleaning up is the proper way of doing it. However given the difficulty of doing so, this "hack" may be acceptable. Note that this solution is probably better than the idea you proposed.
If instead you want to try to explicitly clean up, the "don't use two dots with COM objects" guideline will help you to remember to keep a reference to every object you create so that you can clean them up when you're done.
We use the LifetimeScope class that was described in the MSDN magazine. Using it properly cleans up objects and has worked great with our Excel exports. The code can be downloaded here and also contains the magazine article:
http://lifetimescope.codeplex.com/SourceControl/changeset/changes/1266
Look at my project MS Office for .NET. There is solved problem with referencich wrapper objects and native objects via native VB.NET late-binding ability.
What I'd do:
class ScopedCleanup<T> : IDisposable where T : class
{
readonly Action<T> cleanup;
public ScopedCleanup(T o, Action<T> cleanup)
{
this.Object = o;
this.cleanup = cleanup;
}
public T Object { get; private set; }
#region IDisposable Members
public void Dispose()
{
if (Object != null)
{
if(cleanup != null)
cleanup(Object);
Object = null;
GC.SuppressFinalize(this);
}
}
#endregion
~ScopedCleanup() { Dispose(); }
}
static ScopedCleanup<T> CleanupObject<T>(T o, Action<T> cleanup) where T : class
{
return new ScopedCleanup<T>(o, cleanup);
}
static ScopedCleanup<ComType> CleanupComObject<ComType>(ComType comObject, Action<ComType> actionBeforeRelease) where ComType : class
{
return
CleanupObject(
comObject,
o =>
{
if(actionBeforeRelease != null)
actionBeforeRelease(o);
Marshal.ReleaseComObject(o);
}
);
}
static ScopedCleanup<ComType> CleanupComObject<ComType>(ComType comObject) where ComType : class
{
return CleanupComObject(comObject, null);
}
Usage case. Note the call to Quit, which seems to be necessary to make the process end:
using (var excel = CleanupComObject(new Excel.Application(), o => o.Quit()))
using (var workbooks = CleanupComObject(excel.Object.Workbooks))
{
...
}
For what it's worth, the Excel Refresh Service on codeplex uses this logic:
public static void UsingCOM<T>(T reference, Action<T> doThis) where T : class
{
if (reference == null) return;
try
{
doThis(reference);
}
finally
{
Marshal.ReleaseComObject(reference);
}
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am writing to some tables in a database in C# using a 3rd party database library: Esri file-geodatabase-api.
For each table type I have implemented a writer class.
I pass a reference to a database object to each writer.
Each writer then opens its own table in the database.
Both the database and the table class (3rd party) have Close() methods.
They also implement IDisposable!?
According to Esri samples I should call Close().
Here is a simplified version of my code.
Am I doing things right here? Coming from C++ the automatic garbage collection confuses me.
public class TableWriter : IDisposable
{
// Geodatabase is a 3rd party class that implements IDisposable and has Close() method:
private Geodatabase geoDatabase_;
// Table is a 3rd party class that implements IDisposable and has Close() method:
protected Table table_;
private string tableName_;
private bool disposing_;
public TableWriter(Geodatabase geoDatabase, string tableName)
{
geoDatabase_ = geoDatabase;
tableName_ = tableName;
disposing_ = false;
}
// Constructors of subclasses calls this:
public void CreateTable(List<FieldDef> fieldDefList)
{
table_ = geoDatabase_.CreateTable(tableName_, fieldDefList.ToArray(), "");
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed_)
{
return;
}
if(disposing) // called by user and not garbage collector
{
table_.Close();
table_.Dispose(); // can/should I do both Close and Dispose?
geoDatabase_ = null; // decrement reference count?
}
disposed_ = true;
}
// subclasses override this (they cast TableRow to a subtype):
public virtual void Write(TableRow tableRow){}
}
The export to database is triggered from a gui.
I got a crash when I ran this export many times in sequence.
I have since rewritten my code using the Dispose pattern and have not yet managed to trigger the crash.
The crash seemed a bit random. Sometimes I could run it 5 times in row without a crash other times 15 times in row without a crash.
The stack of the crash is this:
[19352] Exception Details: Cannot access a disposed object. Object name: 'Geodatabase'.
[19352] at Esri.FileGDB.Geodatabase.get_NativeGeodatabase()
[19352] at Esri.FileGDB.Table.Shutdown()
[19352] at Esri.FileGDB.Table.Dispose(Boolean A_0)
To me it seems that the garbage collector called automatic code that double deleted a table in one of the writers.
First, make your class sealed. The rules for implementing IDisposable are considerably simpler for sealed types compared to unsealed types (e.g. you don't need the Boolean disposing parameter).
Then, implement Dispose like so:
public void Dispose()
{
this.table_.Close();
GC.SuppressFinalize(this);
}
While the root cause of your problem is the fact that your Esri.FileGDB library's Dispose method is not idempotent (i.e. a Dispose() call should never throw ObjectDisposedException - it should always be safe to call a single instance's Dispose() multiple times).
I'm assuming that your database library also exposes finalizers (destructors) that incorrectly call .Dispose() or .Close() methods which then cause the ObjectDisposedException.
Would someone explain the following C# code a little bit for me?
I do have knowledge of the normal usage of IDisposable. But I don't understand the following code. The instantiate of new LogLog.LogReceivedAdapter(configurationMessages) looks like have nothing to do with the code block within keyword using. How does statement InternalConfigure(repository, configFile) eventually update variable configurationMessages?
BTW, the code piece was grabbed from log4net XmlConfigurator.cs#508
static public ICollection Configure(ILoggerRepository repository, FileInfo configFile)
{
ArrayList configurationMessages = new ArrayList();
using (new LogLog.LogReceivedAdapter(configurationMessages))
{
InternalConfigure(repository, configFile);
}
repository.ConfigurationMessages = configurationMessages;
return configurationMessages;
}
I do not know that exact code, but it may look like the following:
LogLog registers configurationMessages in some static class (let's call it Log) upon construction;
InternalConfigure uses that static class (and in effect configurationMessages are filled up)
The Dispose() method of LogLog class removes the adapter from the Log class.
The part you presented requires heavy guessing, but I believe, that this is the case.
I believe the constructor of LogReceivedAdapter is an answer.
public LogReceivedAdapter(IList items)
{
this.items = items;
handler = new LogReceivedEventHandler(LogLog_LogReceived);
LogReceived += handler;
}
As you can see it does some magic behind, thus - even though there's no direct reference to newly created instance in your code - it might have some sense :)
C# treats classes that implement IDisposable in one specific way: it calls Dispose() at the moment when the code reaches the closing bracket of the "using" block where the object was created.
Look at Dispose() method of the LogLog.LogReceivedAdapter. The code ensures, that this method is called.
I am in the process of writing an application in C# which will open an Excel spreadsheet (2007, for now) via interop, do some magic, then close. The "magic" part is non-trivial, so this application will contain many references to many COM objects spawned by Excel.
I have written this kind of application before (too many times, in fact) but I've never found a comfortable, "good smell" approach to interacting with COM objects. The problem is partly that, despite significant study, I still don't perfectly understand COM and partly that the interop wrappers hide much that probably shouldn't be hidden. The fact that there are so many different, conflicting suggestions from the community only makes matters worse.
In case you can't tell from the title, I've done my research. The title alludes to this post:
How do I properly clean up Excel interop objects?
First asked in 2008, the advice was really helpful and solid at the time (especially the "Never use 2 dots with com objects" bit) but now seems out of date. In March of 2010, the Visual Studio team posted a blog article warning fellow programmers that Marshal.ReleaseComObject [is] Considered Dangerous. The article referred to two articles, cbrumme's WebLog > ReleaseComObject and The mapping between interface pointers and runtime callable wrappers (RCWs), suggesting that people have been using ReleaseComInterop incorrectly all along (cbrumme: "If you are a client application using a modest number of COM objects that are passed around freely in your managed code, you should not use ReleaseComObject").
Does anyone have an example of a moderately complex application, preferably using multiple threads, that is able to successfully navigate between memory leaks (Excel continues running in the background after the application has closed) and InvalidComObjectExceptions? I'm looking for something which will allow a COM object to be used outside of the context in which it was created but can still be cleaned up once the application is finished with it: a hybrid of memory management strategies which can effectively straddle the managed/unmanaged divide.
A reference to an article or tutorial that discusses a correct approach to this problem would be a much appreciated alternative. My best Google-fu efforts have returned the apparently incorrect ReleaseComInterop approach.
UPDATE:
(This is not an answer)
I discovered this article not long after posting:
VSTO and COM Interop by Jake Ginnivan
I've been able to implement his strategy of wrapping COM objects in "AutoCleanup" classes via an extension method, and I'm pretty happy with the result. Though it does not provide a solution to allow COM objects to cross the boundaries of the context in which they were created and still makes use of the ReleaseComObject function, it does at least provide a neat and easy-to-read solution.
Here's my implementation:
class AutoCleanup<T> : IDisposable {
public T Resource {
get;
private set;
}
public AutoCleanup( T resource ) {
this.Resource = resource;
}
~AutoCleanup() {
this.Dispose();
}
private bool _disposed = false;
public void Dispose() {
if ( !_disposed ) {
_disposed = true;
if ( this.Resource != null &&
Marshal.IsComObject( this.Resource ) ) {
Marshal.FinalReleaseComObject( this.Resource );
} else if ( this.Resource is IDisposable ) {
( (IDisposable) this.Resource ).Dispose();
}
this.Resource = null;
}
}
}
static class ExtensionMethods {
public static AutoCleanup<T> WithComCleanup<T>( this T target ) {
return new AutoCleanup<T>( target );
}
}
did you now the NetOffice concept for COM proxy management?
NetOffice use wrapper classes for com proxies and the IDisposable pattern.
NetOffice keep the parent->child relationship for proxies. dispose a worksheet and all created childs from the instance(cells, styles), etc. was also disposed. you can also use a special event or static property to observe the count of open proxies in your application.
just take a look in this documentation snippet:
http://netoffice.codeplex.com/wikipage?title=Tec_Documentation_English_Management
you find some showstopper projects for com proxy management in the tutorials folder
I have a quite large project which I try to keep as clean and tidy as possible. When I run the code analyzer in Visual Studio I get a reliability error which I find quite annoying. I'd really like to learn how to work around it. Here is a simplified example of what I am doing.
Here is the warning.
Warning 1 CA2000 : Microsoft.Reliability : In method 'MyExampleClassForStackOverflow.AddFeed(string)', call System.IDisposable.Dispose on object 'new FeedClassExamle()' before all references to it are out of scope.
Here is my example code:
class MyExampleClassForStackOverflow : IDisposable
{
public ConcurrentDictionary<string, FeedClassExamle> Feeds { get; set; }
public void AddFeed(string id)
{
//The warning is coming from this code block.
//In the full code, the feed classes collects data on a specific
//interval and feeds them back using events.
//I have a bunch of them and they need to be accessible so I
//store them in dictionaries using keys to effeciently find them.
Feeds.TryAdd(id, new FeedClassExamle());
Feeds[id].Start();
}
public void Dispose()
{
foreach (var item in Feeds)
item.Value.Dispose();
}
}
class FeedClassExamle : IDisposable
{
public void Start()
{
}
public void Dispose()
{
}
}
In order to test the code, use:
using (var example = new MyExampleClassForStackOverflow())
{
}
Any suggestion would be welcome.
The warning exists because the code analysis tools can't determine whether the object will get disposed correctly. The way your code is written, the object will not in fact get disposed correctly, but fixing the code will likely not eliminate the warning.
Fundamentally, what needs to happen is for every the AddFeed method to ensure that something will call Dispose on every FeedClassExample instance it creates. The best approach is to avoid creating a FeedClassExample instance if one already exists in the dictonary under the present ID. Failing that, the AddFeed method should either dispose of any FeedClassExample it creates but then decides not to store in the dictionary, or else swap with the one that is in the dictionary (I'm not sure what methods ConcurrentDictionary supports to do that) and then Dispose the old one. The essential requirement is that at all times outside the actual execution of AddFeed, the dictionary will hold all instances of FeedClassExample that have been created but not destroyed.
It may be informative to add a destructor in your FeedClassExample class which does nothing except log a message. If you are calling Dispose on that class correctly, the destructor will never execute. If you fail to call Dispose, it will. Thus, if the destructor ever executes, you can know you're doing something wrong.
The object isn't getting Disposed of if TryAdd fails, so try doing this explicitly:
public void AddFeed(string id)
{
FeedClassExample fce = new FeedClassExamle();
if (!Feeds.TryAdd(id, fce))
{
fce.Dispose();
}
Feeds[id].Start();
}
Only create the instance if it needs to be added:
if (!Feeds.ContainsKey(id)) {
Feeds.GetOrAdd(id, new FeedClassExamle());
}
The msdn documentation of the System.IDisposable interface states that
The primary use of this interface is to release unmanaged resources.
I'm wondering what are alternative uses.
For example we also needed the IDisposable interface for other allocated resources, such as event subscription and so.
We used the interface as a marker to allow a class instance to know when it's no more used from clients. Client and infrastructural code explicitly call IDisposable.Dispose() whenever they no more need a logical instance of a class implementing the code.
There's no relation with unmanaged resources wrapped from the interface.
When we choosed the IDisposable interface for such a behaviour we considered it as an alternative (undocumented) use of the interface.
Which are the alternative use of IDisposable you have found?
Are they legittimate? Is the MSDN documentation wrong?
I think your reading of the documentation is wrong. Saying that any usage of IDisposable that is not related to unmanaged resources is undocumented is a bit like saying that any usage of System.Int32 that is not counting things is undocumented. It is an interface and has no implementation, there is no functionality there to even begin distinguishing between what's documented and what's undocumented.
The purpose of IDisposable is simply to provide the developer with a mechanism to deterministically control the lifetime of their objects. It just so happens that this mainly a requirement for dealing with unmanaged resources.
One of the more fancy uses of IDisposable is the using block syntactic sugar. As others have mentioned, using blocks give an operation scope and I think those are quite elegant.
Example 1 - timing blocks
StackOverflow uses mini profiler that uses using blocks to identify nested regions of execution:
using (profiler.Step("Doing complex stuff"))
{
using (profiler.Step("Step A"))
{ // something more interesting here
Thread.Sleep(100);
}
using (profiler.Step("Step B"))
{ // and here
Thread.Sleep(250);
}
}
The alternative to not using using is pretty horrible and I don't even want to mock it up here.
Example 2 - Disposable action
There have been different variations of disposable action pattern making rounds in .NET Domain Driven Design circles. Ayende has one, so does Udi Dahan in his Domain Events implementation, Jimmmy Bogard has a slightly different take on this, still in the context of Domain Events. The crux of the pattern is that you want to perform certain actions in some context, then have the context revert back to what it was before after you are done.
Ayende provides a simple example:
class UsuallyReadOnly {
//.. implementation
public IDisposable AllowModification
{
get
{
_allowModification = true;
return new DisposableAction(()=>{ _allowModification = false; } );
}
}
}
And UsuallyReadOnly's usage:
UsuallyReadOnly foo = new UsuallyReadOnly();
using(foo.AllowModification)
{
foo.Name = "Bar";
}
IDisposable is often used in conjunction with using to activate and deactivate something in a definite scope even if it is not an unmanaged resource. The use you describes sound as a reference counting and for sure is not recommended.
For "resources", substitute "responsibilities". When an object is said to hold an unmanaged resource, what that really means is that there is some task that needs to get done sometime, and the object is the only thing with the information and impetus necessary to do it. The purpose of "Dispose" isn't to get rid of any tangible entity, but rather to allow an object to "put its affairs in order". Someone is putting his affairs in order before his death isn't doing anything to himself, but rather he is ensuring that the things he has to do to persons and things outside himself get done. Likewise with IDisposable.Dispose.
Remember there is also the using pattern which acts a bit like RAII.
using ( DisposableObject obj = new DisposableObject( ) )
{
.....
}
So Dispose gets called when the using block is exited.
One of the more popular uses of the IDisposable interface is transaction scopes. You can use it to wrap some SQL logic in a transaction, and explicitly call Complete() to end the transaction:
using (var scope = new TransactionScope())
{
using (var connection = new SqlConnection(connectString))
{
// perform sql logic
...
scope.Complete();
}
}
You could also use a similar pattern for just about anything that requires a temporary function, such as creating and deleting a temporary file:
public class TempFileProvider : IDisposable
{
public Filename { get; private set; }
public TempFileProvider()
{
Filename = Path.GetTempFileName();
}
public void Dispose()
{
File.Delete(Filename);
}
}
So you could use it like:
using (var tempFileProvider = new TempFileProvider())
{
DoSomethingWithFile(tempFileProvider.Filename);
} // deletes temp file
Have a look at the following question Need an alternative to my IDisposable Hack
There i give a nice example of what i used IDisposable for. :)
Granted, it is not the ideal solution, however, it helped me a lot.