How to use IDisposable pattern on Windows Form - c#

I've read about IDisposable pattern on this article and want to implement it in my windows form application. As we know that in windows form .Designer.cs class there is already Dispose method
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
and in .cs class I'm using Typed Dataset to read and save the data.
public partial class frmCustomerList
{
private MyTypedDataSet ds = new MyTypedDataSet();
...
}
So, how to implement IDisposable to dispose MyTypedDataSet? If I implement IDisposable in frmCustomerList and implement its interface
public partial class frmCustomerList : IDisposable
{
private MyTypedDataSet ds = new MyTypedDataSet();
void Dispose()
{
ds.Dispose();
}
}
what about Dispose(bool disposing) method in .Designer.cs?

If you look in the Designer.cs file and look below the dispose method you will see this
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
Only InializeComponent() is warned about not modifing. You can cut (not copy) and paste the protected override void Dispose(bool disposing) out of the designer file and move it in your main code file without worry, just be sure to leave the components.Dispose(); part in as any disposable objects you add through the designer will be put in that collection for disposing.
public partial class frmCustomerList
{
private MyTypedDataSet ds = new MyTypedDataSet();
protected override void Dispose(bool disposing)
{
ds.Dispose();
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
//The rest of your frmCustomerList.cs file.
}

I would dispose any members of the form using one of the forms events such as
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onclosed(v=vs.110).aspx
e.g
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (ds != null)
ds.Dispose();
}

I think you must not care about disposing your class except if you have unmanaged resources. Here is an example where it actually useful:
public class ComplexResourceHolder : IDisposable
{
private IntPtr buffer; // unmanaged memory buffer
private SafeHandle resource; // disposable handle to a resource
public IntPtr Buffer { get { return buffer; } set { buffer = value; } }
public ComplexResourceHolder()
{
this.buffer = ... // allocates memory
this.resource = ... // allocates the resource
}
protected virtual void Dispose(bool disposing)
{
ReleaseBuffer(buffer); // release unmanaged memory
if (disposing)
{
// release other disposable objects
if (resource!= null)
resource.Dispose();
}
}
~ ComplexResourceHolder(){
Dispose(false);
}
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this);
}
}
Check the MSDN for better understanding of Dispose(bool) finalizer override. And this link about unmanaged resources will be useful as well because this is the first reason why you should use IDisposable.
You might wonder to use constructions like below if the class inherits IDisposable:
using (ComplexResourceHolder crh = new ComplexResourceHolder())
{
//Do something with buffer for an instance
//crh.Buffer =
}
Dispose method will be called automatically after closing tag '}'.

Related

Dispose object correctly

Im using VS and a marking in my code tells me to :
"... runChange that is of IDisposable ... change dispose() to dispose object".
But how would i do it correctly - if i put the code in the form.designer's autogenerated dispose() function it says :
"WaitHandle.Dispose(bool) is inaccesible due to protection level"
here is the objects that i want to dispose:
public partial class TestForm : Form
{
private readonly AutoResetEvent runChange = new AutoResetEvent(false);
....
Here is my try to Dispose:
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
runChange.Dispose(true);
base.Dispose(disposing);
}

Dispose service layer object from viewmodel wpf and c#

I'm new to IDisposable concept, I have the following scenario
facing an exception(stackover flow) when I dispose of the object.
I have to create multiple requests(parallel) to get a response from
API.
Like below:
ViewModel
public vm
{
vm(IunityContainer container) { }
public void somemethod
{
await ListofItems.ParallelForEachAsync(async item =>
{
try
{
using (var objectService = _container.Resolve<IobjectService>())
{
var response = await objectService.GeAllItem(request);
concurrentBag.Add(response);
}
}
catch (Exception e)
{
_logger.Error("Failed operation.", e);
}
},maxDegreeOfParallelism: 5);
}
}
Service.cs
public class Service : Idisposable
{
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
this.Dispose();// not sure how to dispose the service layer object which is created
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Issue: since I'm creating multiple objects by a parallel thread when end of the using (}) it throws stackoverflow exception.
solution: I wanted to dispose of "objectService" which is creating
each iteration of the foreach.
please help me resolve this issue.
The stackoverflow error comes from the fact that Dispose() calls Dispose(bool disposing) which back again calls Dispose() on so on until you reach the end of the stack.
It is not a problem of multithreading.
If you look again at the example for IDisposable object given by Microsoft https://learn.microsoft.com/fr-fr/dotnet/api/system.idisposable?view=netframework-4.8 you will see that inside if (disposing) you need to call Dispose on all IDisposable members that the class contains and not on the class itself (not this.Dispose())

What is the correct way to implement IDisposable in C#? [duplicate]

This question already has answers here:
Proper use of the IDisposable interface
(20 answers)
Closed 9 years ago.
I am trying to implement a iDisposable class in c# but the examples in msdn and stackoverflow do not works for me.
And im running a console application in visual studio 2012 framework 4.0
am I missing some using or what?
public class Foo : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
I am following this examples (hyperlinks dont works for me, dont know why):
http://msdn.microsoft.com/en-us/library/ms244737.aspx
Implementing IDisposable correctly
How to implement IDisposable properly
You can find good explanation here Proper use of the IDisposable interface
The short example:
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing) {
if (!this.disposed) {
if (disposing) {
// clean resources here
}
disposed = true;
}
}
private bool disposed = false;
I think this is the standard template more or less:
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
// destroy managed objects here...
}
disposed = true;
}
}
~NameOfClass()
{
Dispose(false);
}
public class MyResource: IDisposable
{
// Pointer to an external unmanaged resource.
private IntPtr handle;
// Other managed resource this class uses.
private Component component = new Component();
// Track whether Dispose has been called.
private bool disposed = false;
public MyResource(IntPtr handle)
{
this.handle = handle;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
CloseHandle(handle);
handle = IntPtr.Zero;
// Note disposing has been done.
disposed = true;
}
}
// Use interop to call the method necessary
// to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
Source: IDisposable Interface
The standard way is to use the Dispose Pattern. See also this.
class MyClass : IDisposable
{
private bool alreadyDisposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// This is called by GC automatically at some point if public Dispose() has not already been called
~MyClass()
{
Dispose(false);
}
// Each derived class should implement this method and conclude it with base.Dispose(disposeManagedResourcesAlso)) call
protected virtual void Dispose(bool disposeManagedResourcesAlso)
{
if (alreadyDisposed) return;
if (disposeManagedResourcesAlso)
{
...dispose managed resources...
}
...dispose unmanaged resources...
alreadyDisposed = true;
}
}
Typical IDisposable implementation could be something like that:
public class Foo: IDisposable {
...
public Boolean IsDisposed {
get;
protected set; // <- Or even "private set"
}
protected virtual void Dispose(Boolean disposing) {
if (IsDisposed)
return;
if (disposing) {
// Release all acquired resources here
}
// You can work with structures (not objects!) here
// Hardly want you to do anything here...
IsDisposed = true;
}
public Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
}

ensuring a well-defined object state when a constructor throws an exception

I have a Visual Studio 2008 C# .NET 2.0CF application. I'm using a component base from which two concrete components are derived. The application first attempts to use SomeDisposableComponent. Its constructor throws an exception because it requires a feature that isn't available. Then, the application tries SomeOtherDisposableComponent. Its construction succeeds.
The problem is that the first component's constructor already added itself to the form's container of components before the exception was thrown. So, when the form is disposed the first component's Dispose() member is called even though the object was never fully constructed. That causes problems for the second component's destructor.
How can I ensure that when the first component throws an exception on construction, the references to it are removed?
public abstract class SomeDisposableComponentBase : Component
{
private System.ComponentModel.IContainer components;
private SomeInternalDisposable s_ = new SomeInternalDisposable();
protected SomeDisposableComponentBase()
{
Initializecomponent();
}
protected SomeDisposableComponentBase(IContainer container)
{
container.Add(this);
Initializecomponent();
}
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
protected abstract void Foo();
#region IDisposable Members
bool disposed_;
protected override void Dispose(bool disposing)
{
// called twice. the first time for the component that failed to initialize properly.
// the second for the one that was used.
if (!disposed_)
{
if (disposing && (components != null))
{
components.Dispose();
}
// on the second call, this throws an exception because it is already disposed.
s_.Close();
disposed_ = true;
}
base.Dispose(disposing);
}
#endregion
}
public SomeDisposableComponent : SomeDisposableComponentBase
{
public SomeDisposableComponent() : base()
{
}
public SomeDisposableComponent(IContainer container) : base(container)
{
// This will throw an exception if it requires a feature that isn't available.
SomeInitFunction();
}
protected override void Foo()
{
// Do something...
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
public partial class my_form : Form
{
private SomeDisposableComponentBase d_;
public my_form()
{
InitializeComponent();
if (null == components)
components = new System.ComponentModel.Container();
try
{
// try the default component
d_ = new SomeDisposableComponent(components);
}
catch (System.Exception)
{
try
{
// the default component requires some feature that isn't available. Try a
// backup component.
d_ = new SomeOtherDisposableComponent(components);
}
catch (System.Exception e)
{
// display error to the user if no suitable component can be found.
}
}
}
/// exit button clicked
private void Exit_Click(object sender, EventArgs e)
{
this.Close();
}
/// from the my_form.designer.cs
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
// this function is executed as expected when the form is closed
components.Dispose();
}
base.Dispose(disposing);
}
}
Thanks,
PaulH
Edit: Removed unused code
The container within the SomeDisposableComponentBase was confusing. It's not relevant to the issue and I should have removed it earlier.
public abstract class SomeDisposableComponentBase : Component
{
private SomeInternalDisposable s_ = new SomeInternalDisposable();
protected SomeDisposableComponentBase()
{
}
protected SomeDisposableComponentBase(IContainer container)
{
container.Add(this);
}
protected abstract void Foo();
#region IDisposable Members
bool disposed_;
protected override void Dispose(bool disposing)
{
// called twice. the first time for the component that failed to initialize properly.
// the second for the one that was used.
if (!disposed_)
{
if (disposing)
{
// on the second call, this throws an exception because it is already disposed.
s_.Close();
}
disposed_ = true;
}
base.Dispose(disposing);
}
#endregion
}
public SomeDisposableComponent : SomeDisposableComponentBase
{
public SomeDisposableComponent() : base()
{
}
public SomeDisposableComponent(IContainer container) : base(container)
{
// This will throw an exception if it requires a feature that isn't available.
SomeInitFunction();
}
protected override void Foo()
{
// Do something...
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
public partial class my_form : Form
{
private SomeDisposableComponentBase d_;
public my_form()
{
InitializeComponent();
if (null == components)
components = new System.ComponentModel.Container();
try
{
// try the default component
d_ = new SomeDisposableComponent(components);
}
catch (System.Exception)
{
try
{
// the default component requires some feature that isn't available. Try a
// backup component.
d_ = new SomeOtherDisposableComponent(components);
}
catch (System.Exception e)
{
// display error to the user if no suitable component can be found.
}
}
}
/// exit button clicked
private void Exit_Click(object sender, EventArgs e)
{
this.Close();
}
/// from the my_form.designer.cs
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
// this function is executed as expected when the form is closed
components.Dispose();
}
base.Dispose(disposing);
}
}
Your form should be in charge of adding items to its components collection - not the components you're adding to the collection. Doing it inside the added components makes it extremely difficult to reason about what's happening in your form.
// It is not obvious that the component is adding itself to the list
new SomeDisposableComponent(components);
// Instead, be explicit where it matters
Component someDisposableComponent = new SomeDisposableComponent(components);
this.components.Add(someDisposableComponent);
Next, to solve your constructor problem, you should move the logic out of the constructor. This is generally good practice - people do not expect constructors to have side effects, and logic in your constructors makes classes difficult to test. If you want to guarantee that something happens every time you create an instance, create a factory and make it so the factory is the only way to get an instance of your class (make the class' constructor internal, or use some other technique):
public class SomeDisposableComponentFactory {
public SomeDisposableComponent CreateInstance() {
SomeDisposableComponent component = new SomeDisposableComponent();
component.SomeInitFunction();
}
}
Finally, you should consider moving the logic for selecting and creating components out of your form and into a general component factory:
public class ComponentFactory {
// The input parameter can be whatever you need to choose the right component
public Component CreateInstance(object input) {
if (input == something) {
SomeDisposableComponent component = new SomeDisposableComponent();
component.SomeInitFunction();
return component;
}
else {
return new AnotherComponent();
}
}
}
Why does container.Add(this) appear before InitializeComponent()? By definition, you're adding an uninitialized component to the container; that's likely to cause problems even if the initialize method doesn't fail.
Just switch the order:
InitializeComponent();
container.Add(this);
That way, if InitializeComponent throws, the component will never add itself to the container. No need for special cleanup.
I'm not sure why you need that constructor at all, but if for some reason it has to be in the order that you already have (i.e. the InitializeComponent method depends on the container... eek), then put the exception handling in the constructor itself:
try
{
container.Add(this);
InitializeComponent();
}
catch (WhateverException)
{
container.Remove(this);
}
But don't do this unless you really have to; much better to just not add the component to the container until it's fully initialized and stable.

Implementing Dispose() with class derived from System.ComponentModel.Component

I made a class that derives from Component:
public class MyComponent: System.ComponentModel.Component
{
}
I saw that Visual Studio put this code in for me:
protected override void Dispose(bool disposing)
{
try
{
if (disposing && (components != null))
{
components.Dispose();
}
}
catch
{
throw;
}
finally
{
base.Dispose(disposing);
}
}
MyComponent has a member that is a DataSet and maybe there's some other members that implement IDisposable. What, if anything, do i need to modify with the Dispose() method to make sure things are cleaned up properly? Thanks for helping.
Change:
if (disposing && (components != null))
{
components.Dispose();
}
to be:
if (disposing && (components != null))
{
_dataset.Dispose();
components.Dispose();
}
Check any disposable member objects and dispose them if they are not null.
I came up with this class:
public class DisposableComponentWrapper : IComponent
{
private IDisposable disposable;
public DisposableComponentWrapper(IDisposable disposable)
{
this.disposable = disposable;
}
public DisposableComponentWrapper(IDisposable disposable, ISite site)
: this(disposable)
{
Site = site;
}
public void Dispose()
{
if (disposable != null)
{
disposable.Dispose();
}
if (Disposed != null)
{
Disposed(this, EventArgs.Empty);
}
}
public ISite Site { get; set; }
public event EventHandler Disposed;
}
and extension method to IContainer:
public static void Add(this IContainer container, IDisposable disposableComponent)
{
var component = (disposableComponent as IComponent);
if(component == null)
{
component = new DisposableComponentWrapper(disposableComponent);
}
container.Add(component);
}
Which might help those willing to enlist disposable resources to their forms.
Note: I'm not certain of the behaviour for IComponent.Disposed, MSDN doesn't say much about how it should be called in implementation of this interface, the documentation sounds like talking about client code registering to the event more than when it should be triggered by implementations of this interface.
Wrap the disposables in components and add them in the components collection. The generated implementation of the dispose pattern will dispose of them correctly.
public partial class MyComponent : System.ComponentModel.Component
{
private readonly System.Data.DataSet _dataSet;
public MyComponent(System.Data.DataSet dataSet)
{
_dataSet = dataSet ?? throw new System.ArgumentNullException(nameof(dataSet));
components.Add(new DisposableWrapperComponent(dataSet));
}
}
The DisposableWrapperComponent is defined thus:
using System;
using System.ComponentModel;
public class DisposableWrapperComponent : Component
{
private bool disposed;
public IDisposable Disposable { get; }
public DisposableWrapperComponent(IDisposable disposable)
{
Disposable = disposable ?? throw new ArgumentNullException(nameof(disposable));
}
protected override void Dispose(bool disposing)
{
if (disposed) return;
if (disposing)
{
Disposable.Dispose();
}
base.Dispose(disposing);
disposed = true;
}
}
Inspired by the answer by #smoothdeveloper.
If you need to be able to reset the data set, encapsulating the lifetime management in a property works quite well.
using System;
using System.ComponentModel;
using System.Data;
public partial class MyComponent : Component
{
private const string DataSetComponentName = "dataSet";
public DataSet DataSet
{
get => (DataSet)((DisposableWrapperComponent)components.Components[DataSetComponentName])
?.Disposable;
set
{
var lastWrapper = (DisposableWrapperComponent)components.Components[DataSetComponentName];
if (lastWrapper != null)
{
components.Remove(lastWrapper);
lastWrapper.Dispose();
}
if (value != null)
{
components.Add(new DisposableWrapperComponent(value), DataSetComponentName);
}
}
}
public MyComponent(DataSet dataSet)
{
DataSet = dataSet ?? throw new ArgumentNullException(nameof(dataSet));
}
}
I used this when implementing a Windows Service that creates a disposable object in OnStart and disposes of it in OnStop.

Categories

Resources