IDisposable Error in Page_Init() - c#

Well this is really frustrating:
I had earlier posted this question in reference to Entity Framework
Using IDisposable in EF and that error is gone now, but I am unable to get this clear:
protected void Page_Init(object sender, EventArgs e)
{
try
{
String testCondition = Request.QueryString["Type"];
switch (testCondition)
{
case "A":
using (var rpt = new Report())
{
List<Class> lst= new ActionDBOClass.ActionMethod();
// other code for crstal report view
//setting datasource of the same report
}
break;
}
}
}
But then also I am getting warning that I must implement dispose on ActionMethod( In fact I have done the Idisposable implementation in the same class like:
public class ActionDBOClass:IDisposable
{
private bool _disposed = true;
public void Dispose()
{
Dispose(_disposed);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
context.Dispose();
// Dispose other managed resources.
}
//release unmanaged resources.
}
_disposed = true;
}
What else I need to do?
I have similar switch case and this is the first one I am showing.

If you don't use lst outside of the Page_Init method, call lst.Dispose() before returning. Something like:
case "A":
using (var rpt = new Report())
{
List<Class> lst= new ActionDBOClass.ActionMethod();
// other code for crstal report view
//setting datasource of the same report
lst.Dispose();
}
break;
A safer method would be to do something like using(List lst= new ActionDBOClass.ActionMethod()){... as this will ensure the Dispose is called if an exception is thrown, or to declare lst outside your try block and call Dispose in the finally block if lst != null.

Related

C# Do I use dispose() correctly?

I studying C# IDisposable now at ASP.NET MVC
I implemented code like this,
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace DisposeTest.Controllers
{
public class TestClass : IDisposable
{
private bool disposed = false;
private Component component = new Component();
private List<string> dataItem = new List<string>();
~TestClass()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// DISPOSE MANAGED RESOURCE
component.Dispose();
}
// DISPOSE UNMANAGED RESOURCE
dataItem = null;
disposed = true;
}
}
public void AddItem()
{
dataItem.Add("wwwwwwwwwwwwwww");
}
}
}
using System.Web.Mvc;
namespace DisposeTest.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
TestClass tc = new TestClass();
tc.AddItem();
tc.dispose();
return View();
}
}
}
After When I push F5 to launch Visual studio debugger with web browser, debugger catch into destructor. But after I refreshed web browser again or hit enter browser address, debugger did not catch destructor.
I would like to know some answers.
ASP.NET MVC call destructor after every controller action?
Do I correctly used Dispose()?
Should I clear variables even private member field?
Thank you for your your adivices
ps. I added to call dispose() method after doing add();
For example. We have CatDataStore class who works with data base and implements IDisposable. This is full implements IDisposable:
class CatDataStore : IDisposable
{
//data context contains models, connection string... etc
private ApplicationDbContext _context = new ApplicationDbContext();
private bool disposed;
public async Task<bool> AddItem(Cat item)
{
await _context.Cats.AddAsync(item);
await _context.SaveChangesAsync();
return true;
}
//smth CRUD methods..
public void Dispose()
{
Dispose(true);
//GC can't eat this
GC.SupressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (disposed)
throw new ObjectDisposedException();
_context.Dispose();
}
disposed = true;
}
~CatDataStore() => Dispose(false);
}

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())

How to automatically dispose objects inside List?

I have a class with resources which I need to dispose:
class Desert: IDisposable
{
private object resource; // handle to a resource
public Desert(string n)
{
// Create resource here
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (resource != null) resource.Dispose();
}
}
}
I wonder if there is any way to automatically ask framework to call Dispose on each element, whenever the List object is going to be destroyed, just like I would have destructor. Currently I am looping through the list and calling Dispose:
// On form open
List<Desert> desertList = new List<Desert>();
for(int i = 0; i < 10; i++)
{
desertList.Add(new Desert("Desert" + i));
}
// On form closing
for (int i = 0; i < 10; i++)
{
desertList[i].Dispose();
}
Is it the only way to dispose objects inside List?
You could extend the List type itself:
public class AutoDisposeList<T> : List<T>, IDisposable where T : IDisposable
{
public void Dispose()
{
foreach (var obj in this)
{
obj.Dispose();
}
}
}
using (var myList = new AutoDisposeList<Desert>())
{
}
If you need more than that, you could look at Finalizers. These aren't quite destructors - they are methods that run JUST before an object is Garbage Collected. It's very easy to go wrong with these though, my vote is for a using statement.
see: https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx

C# Using Clause - Clarification

I understand what the using clause does, but should it be used with unnamed parameters?
For example; should:
var navigator = new XPathDocument(new StringReader(request)).CreateNavigator();
be:
using (StringReader sr = new StringReader(request))
{
var navigator = new XPathDocument(sr).CreateNavigator();
...
}
It makes no difference whether you are assigning the object implementing IDisposable to a variable, you should still be disposing it and hence you should use Using.
Best way to know how it works : test!
class Program
{
public static void Main()
{
using (TestDisposable d = new TestDisposable())
{
} // Will trace "disposed"
UseDisposable use = UseDisposable.Create(new TestDisposable());
// Will trace "disposed"
}
}
public class UseDisposable
{
public TestDisposable Disposable;
public static UseDisposable Create(TestDisposable disposable)
{
return new UseDisposable()
{
Disposable = disposable
};
}
}
public class TestDisposable : IDisposable
{
private bool _disposed = false;
#region IDisposable Membres
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if(!_disposed && disposing)
{
Trace.WriteLine("Disposed");
_disposed = true;
}
}
#endregion
}
In my opinion, you should always use the second method.
Your first code piece is equivalent to this:
StringReader sr = new StringReader(request);
var navigator = new XPathDocument(sr).CreateNavigator();
The difference is that you dont create an explicit "handle" for your StringReader and therefore lose the ability to work with it later on (e.g.: disposing it).
Therefore you should be using the "using" clause. It also enhances the readability.
Yes you should use this if you can. I think the MS code analysis even warns you if you don't.

Getting COM exception when using Interop in a .net app

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().

Categories

Resources