I application that uses a a Interop Com Object. Therefore I had written a wrapper class, to do the freeing in the dispose or if this is not done in the finalizer. So I can use the using keyword, to ensure a freeing is done.
Is using this pattern a good way? Or is there even a class in the Framework that is doing this for me?
class ComWrapper<T> : IDisposable
{
private readonly T comObject;
private bool disposed = false;
public ComWrapper(T comObject)
{
this.comObject = comObject;
}
~ComWrapper()
{
this.Dispose(false);
}
public T ComObject
{
get
{
return this.comObject;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if (this.disposed)
{
return;
}
Marshal.FinalReleaseComObject(this.comObject);
}
}
I personally wouldn't recommend this because it seems somewhat pointless. But, I would recommend having a static class called Utility, with this method:
public static void disposeComObject<T>(ref T comObject)
{
if(Marshal.IsComObject(comObject) && comObject != null)
{
//You need to save the object
if(typeof(T) == typeof(Microsoft.Office.Interop.Excel.Workbook))
{
((Microsoft.Office.Interop.Excel.Workbook))comObject.Save();
((Microsoft.Office.Interop.Excel.Workbook))comObject.Close();
}
//You need to save the object
if(typeof(T) == typeof(Microsoft.Office.Interop.Excel.Application))
{
((Microsoft.Office.Interop.Excel.Application))comObject.Quit();
}
Marshal.ReleaseComObject(comObject);
comObject = null;
}
}
Now From Code, you can call this like so
...
Microsoft.Office.Interop.Excel comObject = null;
try{
//Open comObject
//Here I would call some functions, and have nested exceptions
}
catch(nestedException err)
{
//Handle at your discretion
}
finally{
Utility.disposeComObject(ref comObject);
}
This is specific to the Excel Namespace, but adjusting it should be easy enough.
Related
The Disposable pattern is one that is re-implemented on a per class basis. So, I was looking for a way to generalize it. The problem I ran into a few years ago is that, even if you implement it as class itself, you can't have an object derive from both your Disposable implementation and from another class (C# doesn't support multi-inheritance).
The question is, how do you make a generic way to have the Disposable pattern implemented so you don't need to write it explicitly per class that implements IDisposable?
Here is the standard Disposable pattern that is generated for you by Visual Studio (VS 2015).
public class TestClass : IDisposable {
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing) {
if (!disposedValue) {
if (disposing) {
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~DisposeTest() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose() {
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
My implementation
So, here is the solution I came up with.
public class DisposeService<T> where T : IDisposable {
private readonly T _disposee;
public Action<T> ManagedAction { get; set; }
public Action<T> UnmanagedAction { get; set; }
public DisposeService(T disposee, Action<T> managedAction = null, Action<T> unmanagedAction = null) {
_disposee = disposee;
ManagedAction = managedAction;
UnmanagedAction = unmanagedAction;
}
private bool _isDisposed;
public void Dispose(bool isDisposing) {
if (_isDisposed) return;
if (isDisposing && ManagedAction != null) {
ManagedAction(_disposee);
}
var hasUnmanagedAction = UnmanagedAction != null;
if (hasUnmanagedAction) {
UnmanagedAction(_disposee);
}
_isDisposed = true;
if (isDisposing && hasUnmanagedAction) {
GC.SuppressFinalize(_disposee);
}
}
}
This class allows you to create a DisposableService<> member for your class that implements IDisposable. Here is an example on how to use it when you only have managed resources.
public class TestClass : IDisposable {
protected readonly DisposeService<TestClass> DisposeService;
private readonly SafeHandle _handle;
public TestClass() {
DisposeService = new DisposeService<TestClass>(this, ps => { if (_handle != null) _handle.Dispose(); });
_handle = new SafeFileHandle(IntPtr.Zero, true);
}
public void Dispose() {
DisposeService.Dispose(true);
}
}
How it works
The DisposeService will run it's Dispose on your object's Dispose.
The DisposeService's dispose will run your Managed and Unmanaged Action that you provide on initialization (or update in derived classes).
The GC.SuppressFinalize will run automatically if an UnmanagedAction is provided.
Always make sure to create the DisposableService<> as the first action of your constructor.
So, here is an example of using this service with unmanaged resources.
public class TestClass : IDisposable {
protected readonly DisposeService<TestClass> DisposeService;
private readonly SafeHandle _handle;
public TestClass() {
DisposeService = new DisposeService<TestClass>(this,
ps => { if (_handle != null) _handle.Dispose(); },
ps => { /* Free unmanaged resources here */ });
_handle = new SafeFileHandle(IntPtr.Zero, true);
}
public void Dispose() {
DisposeService.Dispose(true);
}
~TestClass() {
DisposeService.Dispose(false);
}
}
And, an example of making a derived class from the class above.
public class TestClassDerived : TestClass, IDisposable {
private readonly SafeHandle _derivedHandle;
public TestClassDerived() {
// Copy the delegate for the base's managed dispose action.
var baseAction = DisposeService.ManagedAction;
// Update the managed action with new disposes, while still calling the base's disposes.
DisposeService.ManagedAction = ps => {
if (_derivedHandle != null) {
_derivedHandle.Dispose();
}
baseAction(ps);
};
_derivedHandle = new SafeFileHandle(IntPtr.Zero, true);
}
}
Easy peasy lemon squeezy. You keep the reference to the base's delegate and call it as part of the derived class's delegate.
Overall, should be cleaner then managing that procedural region of blarg that Microsoft has been providing since 2005...
Edit: I thought the 'this' being passed in the constructor might be a concern. But, it doesn't seem to be: Is it a bad practice to pass "this" as an argument? Just remember to put the null checks in your actions so you don't try to Dispose something that is null. :-)
If you profile a simple client application that uses SocketAsyncEventArgs, you will notice Thread and ExecutionContext allocations.
The source of the allocations is SocketAsyncEventArgs.StartOperationCommon that creates a copy of the ExecutionContext with ExecutionContext.CreateCopy().
ExecutionContext.SuppressFlow seems like a good way to suppress this allocation. However this method itself will generate allocations when ran in a new thread.
How can I avoid these allocations?
SocketAsyncEventArgs
public class SocketAsyncEventArgs : EventArgs, IDisposable {
//...
// Method called to prepare for a native async socket call.
// This method performs the tasks common to all socket operations.
internal void StartOperationCommon(Socket socket) {
//...
// Prepare execution context for callback.
if (ExecutionContext.IsFlowSuppressed()) {
// This condition is what you need to pass.
// Fast path for when flow is suppressed.
m_Context = null;
m_ContextCopy = null;
} else {
// Flow is not suppressed.
//...
// If there is an execution context we need
//a fresh copy for each completion.
if(m_Context != null) {
m_ContextCopy = m_Context.CreateCopy();
}
}
// Remember current socket.
m_CurrentSocket = socket;
}
[Pure]
public static bool IsFlowSuppressed()
{
return Thread.CurrentThread.GetExecutionContextReader().IsFlowSuppressed;
}
//...
}
ExecutionContext
[Serializable]
public sealed class ExecutionContext : IDisposable, ISerializable
{
//...
// Misc state variables.
private ExecutionContext m_Context;
private ExecutionContext m_ContextCopy;
private ContextCallback m_ExecutionCallback;
//...
internal struct Reader
{
ExecutionContext m_ec;
//...
public bool IsFlowSuppressed
{
#if !FEATURE_CORECLR
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
get { return IsNull ? false : m_ec.isFlowSuppressed; }
}
} //end of Reader
internal bool isFlowSuppressed
{
get
{
return (_flags & Flags.IsFlowSuppressed) != Flags.None;
}
set
{
Contract.Assert(!IsPreAllocatedDefault);
if (value)
_flags |= Flags.IsFlowSuppressed;
else
_flags &= ~Flags.IsFlowSuppressed;
}
}
[System.Security.SecurityCritical] // auto-generated_required
public static AsyncFlowControl SuppressFlow()
{
if (IsFlowSuppressed())
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes"));
}
Contract.EndContractBlock();
AsyncFlowControl afc = new AsyncFlowControl();
afc.Setup();
return afc;
}
//...
}//end of ExecutionContext.
AsyncFlowControl
public struct AsyncFlowControl: IDisposable
{
private bool useEC;
private ExecutionContext _ec;
//...
[SecurityCritical]
internal void Setup()
{
useEC = true;
Thread currentThread = Thread.CurrentThread;
_ec = currentThread.GetMutableExecutionContext();
_ec.isFlowSuppressed = true;
_thread = currentThread;
}
}
Thread
// deliberately not [serializable]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(_Thread))]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Thread : CriticalFinalizerObject, _Thread
{
//...
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal ExecutionContext.Reader GetExecutionContextReader()
{
return new ExecutionContext.Reader(m_ExecutionContext);
}
}
The only way to set isFlowSuppressed to true, to pass the condition in the StartOperationCommon method, is by calling Setup method, and the only call to Setup is in SuppressFlow method, wich you have discussed.
As you can see, SuppressFlow is the only solution.
Actually, SuppressFlow doesn't allocate. It returns a AsyncFlowControl, which is a struct. The proper solution basically is to call SendAsync and ReceiveAsync as follows:
public static bool SendAsyncSuppressFlow(this Socket self, SocketAsyncEventArgs e)
{
var control = ExecutionContext.SuppressFlow();
try
{
return self.SendAsync(e);
}
finally
{
control.Undo();
}
}
public static bool ReceiveAsyncSuppressFlow(this Socket self, SocketAsyncEventArgs e)
{
var control = ExecutionContext.SuppressFlow();
try
{
return self.ReceiveAsync(e);
}
finally
{
control.Undo();
}
}
I created these extension methods to make this a bit simpler and more explicit.
Traces with dotMemory showed that memory allocations really do go down to zero.
Create class MustDispose.cs
public class MustDispose
{
public MustDispose()
{
}
}
in.aspx Page
protected void Page_Load(object sender, EventArgs e)
{
using (MustDispose obj = new MustDispose)
{
// use the object
}
}
errorr
Destructors and object.Finalize cannot be called directly. Consider
calling IDisposable.Dispose if available.
You class has to impplement IDisposable, in oder to be used inside using statement.
Example:
public class MustDispose : IDisposable
{
public MustDispose()
{
}
//implement Dispose
public void Dispose()
{
....
}
}
reading from using:
Provides a convenient syntax that ensures the correct use of
IDisposable objects.
You need to implement IDisposable like so:
class TestDispose : IDisposable
{
public TestDispose()
{
...
}
public void Dispose()
{
// dispose of your resources here
}
}
Then you will be able to use it in a using block which automatically calls obj.Dispose at the end of the block.
using (var obj = new TestDispose())
{
...
}
Is like:
var obj = new TestDispose();
try
{
...
}
finally
{
obj.Dispose();
}
I have a COM type (created using tlbimp.exe) and a C# class that wraps this object. I want to perform some clean up in the finalizer for my C# wrapper. Following the guidelines here I might write something like this:
public class MyClass : IDisposable
{
private IMyComObject comObject;
public MyClass()
{
comObject = new MyComObject();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MyClass()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
// Be tollerant of partially constructed instances
if (comObject != null)
{
comObject.Cleanup();
// Account for object being disposed twice
comObject = null;
}
}
// Other bits go here...
}
I know that finalizers can run in any order and so I should not attempt to use any object that implements a finalizer, however as far as I can tell tlbimp generated COM types don't implement a finalizer and so the above should be OK.
I haven't been able to find any official documentation on this however, so my question is is it safe to reference and use COM objects in a finalizer?
I created a abstract com wrapper class, from which I derive all my com wrapper classes. It works very well. My original code is VB, since I need late binding (this was before C# introduced the dynamic type). The rest of my app is written in c#.
public abstract class ComWrapper : IDisposable
{
protected internal object _comObject;
protected ComWrapper(object comObject)
{
_comObject = comObject;
}
#region " IDisposable Support "
private bool _disposed = false;
protected virtual void FreeManagedObjects()
{
}
protected virtual void FreeUnmanagedObjects()
{
ReleaseComObject(_comObject);
}
private void Dispose(bool disposing)
{
if (!_disposed) {
if (disposing) {
FreeManagedObjects();
}
FreeUnmanagedObjects();
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override void Finalize()
{
Dispose(false);
base.Finalize();
}
#endregion
}
and
public static class Helpers
{
public static void ReleaseComObject(ref object o)
{
if ((o != null)) {
try {
Marshal.ReleaseComObject(o);
} catch {
} finally {
o = null;
}
}
}
public static string ToDotNetString(object comString)
{
if (comString == null) {
return string.Empty;
}
string s = comString.ToString();
ReleaseComObject(ref comString);
return s;
}
}
I've a C# class which uses a COM component using interop.
Here is the sample code:
public class MyClass
{
MyCOMClass myObj=null;
try
{
myObj = new MyCOMClass();
for (int num = 0; num < myArr.Length; num++)
{
//Call a method on myObj and do some processing
}
}
catch(Exception ex)
{
//log exception
}
finally
{
if (myObj != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(myObj);
}
}
}
Here, the for loop runs for about 150 times.
n executing this code, in the catch block, am getting an exception :
"COM object that has been separated from its underlying RCW cannot be used."
I tried implementing IDisposable interface and then writing Dispose method:
public class MyClass: IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true);
}
protected virtual void Dispose(bool diposeMgdResources)
{
if (!this.disposed)
{
if (diposeMgdResources)
{
if (myObj != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(myObj);
}
}
this.disposed = true;
}
}
}
From the client, I then call dispose on this class like:
myClass.Dispose();
But, still am getting the same exception here.What am I missing?
Thanks for reading.
Take a look at this article:
Marshal.ReleaseComObject considered dangerous
You probably don't want to call Marshal.ReleaseComObject().