all. I've never worked with destructors nor dispose, so this is new to me.
I have a task of doing a class that has destructor and dispose methods, and that has a UInt64 Id property that is auto-incremental, and a static Dictionary<UInt64,MyClass> that must reference by Id all live instances of MyClass.
After searching how to use them properly, this is what I ended up doing:
public class MyClass : IDisposable
{
private static Object Lock = new Object();
private static Dictionary<UInt64, MyClass> LiveInstances = new Dictionary<UInt64, MyClass>();
public UInt64 Id { get; private set; }
public MyClass()
{
lock (Lock)
{
var newId = IncrementalId();
if (newId == 0)
{
throw new ArgumentException("Reached MAX VAL");
}
Id = newId;
LiveInstances.Add(Id, this);
}
}
~MyClass()
{
CleanUpNativeResources();
}
public void Dispose()
{
lock (Lock)
{
CleanUpManagedResources();
CleanUpNativeResources();
GC.SuppressFinalize(this);
}
}
protected virtual void CleanUpManagedResources()
{
LiveInstances.Remove(Id);
}
protected virtual void CleanUpNativeResources()
{
}
private static UInt64 IncrementalId()
{
for (ulong i = 0; i <= Convert.ToUInt64(LiveInstances.Count) ; i++)
{
if (i != UInt64.MaxValue && !LiveInstances.ContainsKey(i + 1))
{
return i+1;
}
}
return 0;
}
}
Now, my question is How do I dispose objects? Whether I try to find examples of disposing objects, I find something like this:
// Code to dispose the managed resources of the class
Console.WriteLine("Object disposed");
Thanks in advance.
Managed resources will be disposed automatically by the garbage collector at some point of time. Unmanaged resources are things like Filehandles, obtained by making a Windows API call that returns a Windows Handle which must be freed manually. You dont have anything which requires manual disposal.
If you don't free those handles, they will remain allocated for the duration of the program, but all .Net classes that have an unmanaged resource provide a Finalizer (see below) to make sure that they will normally be freed at some point.
(But if you were writing your own file handling class and forgot to free the file handle anywhere at all, the file would remain open until your program exited.)
Normally such unmanaged resources will be freed in two places:
The Dispose() method. This should be the normal way that you dispose unmanaged resources.
The Finalizer. This is a last-resort mechanism. If a class has a finalizer it will be called by the Garbage Collector when it cleans up a dead object. Any class which has an unmanaged resource should have a finalizer to clean up if the programmer forgets to call Dispose().
The basic Dispose pattern used goes something like this:
class MyObject : IDisposable
{
//indicates if dispose has already been called
//private bool _disposed = false;
//Finalize method for the object, will call Dispose for us
//to clean up the resources if the user has not called it
~MyObject()
{
//Indicate that the GC called Dispose, not the user
Dispose(false);
}
//This is the public method, it will HOPEFULLY but
//not always be called by users of the class
public void Dispose()
{
//indicate this was NOT called by the Garbage collector
Dispose(true);
//Now we have disposed of all our resources, the GC does not
//need to do anything, stop the finalizer being called
GC.SupressFinalize(this);
}
private void Dispose(bool disposing)
{
//Check to see if we have already disposed the object
//this is necessary because we should be able to call
//Dispose multiple times without throwing an error
if (!disposed)
{
if (disposing)
{
//clean up managed resources
components.Dispose();
}
//clear up any unmanaged resources - this is safe to
//put outside the disposing check because if the user
//called dispose we want to also clean up unmanaged
//resources, if the GC called Dispose then we only
//want to clean up managed resources
}
}
}
Related
I have a test program that implements ManagedClass with both Dispose method and a Finalizer.
I'm forcing garbage collection via GC.Collect(), but Finalizer is only called if an object is created in a separate method. Why is that?
namespace FinalizerTest
{
internal class Program
{
static void Run()
{
ManagedClass mc = new ManagedClass();
mc.StartWriting();
}
static void Main(string[] args)
{
Console.WriteLine("Let's test Finalizers!");
// Test #1: Create object through another method
Console.WriteLine("Test #1");
Run();
GC.Collect();
GC.WaitForPendingFinalizers();
// Test #2: Create object directly in Main
Console.WriteLine("Test #2");
ManagedClass mc1 = new ManagedClass();
mc1.StartWriting();
mc1 = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadLine();
}
}
public class ManagedClass : IDisposable
{
private StreamWriter _writer;
public void StartWriting()
{
_writer = new StreamWriter("output.txt");
}
public void Dispose()
{
Console.WriteLine("Disposing");
_writer?.Dispose();
GC.SuppressFinalize(this);
}
~ManagedClass()
{
Console.WriteLine("Finalizing");
_writer?.Dispose();
}
}
}
As I understand it in both scenarios a reference to the object is lost.
First test - reference is lost by exiting the scope of the method
Second test - reference is lost by setting reference variable to null
However, Finalizer is consistently only ever called after the first test.
According to Microsoft documentation:
The garbage collector then calls the Finalize method automatically under the following conditions:
After the garbage collector has discovered that an object is inaccessible, unless the object has been exempted from finalization by a call to the GC.SuppressFinalize method.
I'm not calling GCSuppressFinalize and according to Visual Studio I'm working on .NET 7.0
I tried:
Reassigning a new reference instead of null
Implementing Finalizer without the Dispose method
Running in Release configuration / building the project and running the application directly through exe file
None of those things called Test #2 Finalizer
Sometimes GC.Collect doesn't work perfectly.
To improve the garbage collection, I call the following procedure :
internal static void CollectGarbage(int SizeToAllocateInMo)
{ // set SizeToAllocateInMo to -1 to force garbage collection without testing available memory.
long [,] TheArray ;
bool DoCollect=SizeToAllocateInMo<0 ;
if (!DoCollect) try { TheArray = new long[SizeToAllocateInMo,125000] ; } catch { DoCollect=true ; }
TheArray=null ;
if (DoCollect)
{
GC.Collect() ;
GC.WaitForPendingFinalizers() ;
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle,-1,-1) ;
GC.Collect() ;
}
}
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize); // used for garbage collection
[There is a similar question Shared ownership of IDisposable objects in C# but the accepted answer suffers from similar design problems which my solution has]
I have been trying to think around this problem having seen many designs taking a blind leap of faith in garbage collector when working in c#. Reason being many times its easy to ignore that one need to handle the IDisposable rather carefully making them close equivalent of resource allocation in c++. I understand that pedantically speaking Dispose is not the equivalent of c++ destructor but if you are holding on to native resources which needs to be cleaned in a deterministic manner it becomes very similar.
But if the object is shared by multiple resources (for eg. an HttpClient object which is meant to be created and used concurrently for performance), who owns the responsibility of calling Dispose since there is no single owner? To solve this problem I came up with a SharedOwner library which has a similar interface as shared_ptr.
Code snippet:
SharedOwner:
public static SharedHandle<T> MakeSharedHandle(Func<T> createSharedOwner)
{
var obj = new SharedHandle<T>(createSharedOwner());
return obj;
}
public SharedHandle(T obj)
{
AddReference();
m_object = obj;
}
public Handle<T> GetHandle()
{
AddReference();
return new Handle<T>(this);
}
internal void Decrement()
{
if (Interlocked.Decrement(ref m_refCounter) == 0)
{
m_object.Dispose();
m_object = default(T);
}
}
internal T GetInternalHandler() { return m_object; }
private void AddReference()
{
Interlocked.Increment(ref m_refCounter);
}
~SharedHandle()
{
m_object.Dispose();
}
Handle
is a transparent wrapper that manages the ref counting calls keeping that abstracted from consumers.
public sealed class Handle<T> : IDisposable where T : IDisposable
{
private SharedHandle<T> m_handle;
bool disposed = false;
internal Handle(SharedHandle<T> handle) { m_handle = handle; }
public void Dispose()
{
if (!disposed)
{
m_handle.Decrement();
GC.SuppressFinalize(this);
disposed = true;
}
}
~Handle()
{
if (!disposed)
{
m_handle.Decrement();
}
}
The typical usage pattern that I imagined would be:
using (var sharedClient = this.m_sharedClient.GetHandle()) // m_sharedClient is the SharedHandle passed
{
var httpClient = (HttpClient)sharedClient;
// use httpClient
}
Now I see two issues with this approach which deviate it from the original motivation of simulating shared_ptr behavior:
The first reference is held by SharedHandle itself. So even when all Handles are out of scope one reference would still be held by SharedHandle thereby making the if block in Decrement unreachable.
The final Dispose happens when the SharedHandle dies which in lot of sense is no better than not calling Dispose on the underlying object itself. Hence making the solution much less valuable.
I am thinking of moving the reference counting to Handle and using SharedHandle as the control block in shared_ptr but then that means that one may end up with a valid SharedHandle object holding on to a Disposed internal object.
Another alternative that I can think of is making SharedHandle derive from IDisposable and just call Decrement in Dispose. But then this brings other set of design issues. Is there anything that can be done to solve this problem in a more elegant way?
I have a class which instantiates a few unity game objects in a scene hierarchy. This class implements IDisposable. Should I handle these game objects as they were managed or unmanaged resources?
I am following the Dispose pattern, so where should I put calls like GameObject.Destroy(myGameObject)?
Thank you
Edit:
Ok, lets say I want to destroy the game objects instantiated by this class when it goes out of scope. How would you proceed then?
Edit 2:
I was testing the dispose. And I have found a solution. It doesnt work automatically, because GameObject.Destroy(myGameObject) cant be called from different thread. It will throw an error CompareBaseObjectsInternal. So, when no longer needed I call myClass.Dispose(). Also it seems irrelevant whether I handle Unity GameObject as managed or unmanaged.
myMain()
{
DisposeTestClass test = new DisposeTestClass();
//...
test.Dispose();
}
class DisposeTestClass : System.IDisposable
{
public GameObject uselessGameobject { get; private set; }
public DisposeTestClass()
{
uselessGameobject = new GameObject("Useless gameobject");
}
#region IDisposable
private bool _disposed;
~DisposeTestClass()
{
Debug.Log("~DisposeTestClass()");
this.Dispose(false);
}
public void Dispose()
{
Debug.Log("Dispose()");
this.Dispose(true);
System.GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
Debug.Log("Dispose(bool)");
if(_disposed)
{
Debug.Log("Disposed. Return.");
return;
}
if(disposing)
{
Debug.Log("Disposing of managed resources...");
// clean up managed resources
/*
if(uselessGameobject != null)
{
GameObject.Destroy(uselessGameobject);
Debug.Log("Game object destroyed.");
}
else
{
Debug.Log("Game object is null.");
}*/
}
Debug.Log("Cleaning up unmanaged resources...");
// clean up unmanaged resources
if(uselessGameobject != null)
{
GameObject.Destroy(uselessGameobject);
Debug.Log("Game object destroyed.");
}
else
{
Debug.Log("Game object is null.");
}
// set the flag
Debug.Log("Setting the disposed flag.");
this._disposed = true;
}
#endregion
}
}
No, you shouldn't implement IDisposable. But you can :).
"so where should I put call GameObject.Destroy(myGameObject)" And when you want your objects to be destroyed? Actually that doesn't matter whether you call myContainer.Dispose() or GameObject.Destroy(gObj).
The only reason to implement IDisposable for you is to write "convient" code like:
using(var container = new MyContainer())
using(var somethingElse = new MyObject())
{
\\Logic for container and somethingElse
}
But in Unity this makes no sense. I can hardly imagine case when in an Update GameObjects are created and then destroyed.
Huh, I think you slightly misunderstood what IDisposable and using statement is used for. You shouldn't implement IDisposable everywhere just to get rid of an object - this is garbage collector role, it knows better when an object shoyld be disposed.
IDisposable and using statement are used as a try/finally statement(of course it is much more complicated under the hood) and ensure that an object is removed/resolved right after it is not used anymore. It is not always a managed/unmanaged resource issue.
Using using statement won't ensure that your game object will be disposed. It all depends on the fact whether there are another objects pointing to it. Since it looks like a root object, I believe it will be held as long as possible by GC. Note that even if GC call Dispose() on your object, as long as it is referenced, it will be stay on the special queue until it is released.
On the other hand if your GameObject is less the Game, more the Object, you shouldn't consider disposing it using IDisposable as long as it is not somehow connected with some connection/file/external resource. GC will claim memory as soon as your object is considered garbage. Just take into consideration, that IDisposable is something which CLR treats a bit different and is not always the way to go.
EDIT
According to your question from edit - basically when a objects goes out of scope, you do nothing - if GC considers it garbage, it will be removed with the closest GC collection that occur. That's why C# is considered managed language and why you do not release memory on your own.
I have created a class to store search values to a session. Such that when I get back to the search page from another page, I can get the values stored in the session. When the search page loads, I'm getting the values from the session, fill up the text fields and dispose the object afterwards. But I get a StackOverflowException when I try to dispose the object. Why does this happen and how do I fix it?
public class SearchValue : IDisposable{
public int ID {get; set;}
public string Name {get; set;}
public void Dispose()
{
this.Dispose();
}
}
public void SaveSearchValueToSession()
{
SearchValue searchValue = new SearchValue();
searchValue.ID = Convert.ToInt32(txtID.Text);
searchValue.Name = txtName.Text;
Session["SEARCH_VALUE"] = searchValue;
}
protected void Page_Load(object sender, EventArgs e){
SearchValue searchValue = (SearchValue)Session["SEARCH_VALUE"];
txtID.Text = searchValue.ID.ToString();
txtName.Text = searchValue.Name;
//Right here I would like to dispose the object
searchValue.Dispose()
}
You are calling the same method from inside the Dispose method. This will indeed cause a StackOverflowException. I do wonder if you really need to implement IDisposable and if you understand its purpose...
If you really need to:
Give a meaningful implementation of Dispose, free unmanaged resources, etc;
Use using around the variable;
Don't save it inside the Session after disposal.
Also read the Fundamentals of Garbage Collection.
From comments I notice you are worried of creating too much objects. Don't worry, it is no problem here. This is especially true since your object (single) doesn't get garbage collected now: you save it in the session where it will live until the session is distroyed. You keep reusing the very same object over and over again.
Your problem stems from the improper way to implement the IDisposable pattern. Here is a short but complete example for implementing it:
public class ThisIsDisposable : IDisposable
{
public ThisIsDisposable() { }
private bool _isDisposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (!_isDisposed)
{
//Do your unmanaged disposing here
_isDisposed = true;
}
}
}
}
If the class is sealed, then the second Dispose(bool) method should be marked private and not virtual. The primary use of IDisposable is to dispose of unmanaged resources. If you don't have unmanaged resources, you can still implement it so that the object can be used in using statements, but generally the Dispose(bool) overload will not do anything in that case.
See CA1063 (https://msdn.microsoft.com/en-us/library/ms244737.aspx) and IDisposable Interface (https://msdn.microsoft.com/library/system.idisposable.aspx)
As your comments have said, using IDisposable will not automatically free memory. Your object will be garbage collected when there are no more references to the object. Storing references to your values and never removing those references will result in a memory leak, so if you want to make sure that you don't leak memory, then you need to make sure that there are no more active references to the objects you create (clear the list/session object,etc).
In your case, it is completely unnecessary to implement this pattern because your objects are not used in using statements and they don not consume managed resources.
Using sessions is a hard battle. Personally, I only EVER use them for account login status. A query string would help you out here. See the example below.
Page Before
Response.Redirect("http://yoursite.com/search?id=12");
Then on the search page (assuming) (Page Load)
// usual if(!Page.PostBack)
int searchId = -1;
if(Request.QueryString.Count > 0)
{
String searchIdStr = Request.QueryString["id"]
if(searchIdStr != String.Empty)
{
try{
searchId = Convert.ToInt32(searchIdStr);
SearchValue searchValue = searchValueRepo.GetSearchValues()
.Find(o => o.ID == searchId);
if(searchValue == null){
//Failed to find your search values
}
} catch (Exception ex) { //failed to convert to integer };
}
}
Then, if you feel that the user has too much control over the query string you can then set id=239847hcjdhnsjk or a salted hash so no one can attempt to change the value to change the behavior of the site.
I've seen this error on other posts, but not for this exact situation.
I have two classes that do the same thing with a MessageQueue. Because of that, I abstracted the creation and disposal of the queue to a helper class. I'm getting this error, and I can't see how the queue can be disposed more than once.
Object 'messageQueue' can be disposed more than once in method 'MsmqHelper.DisposeQueue(MessageQueue)'
In one of the classes, this is how the queue is used:
private MessageQueue _messageQueue;
Then, in the constructor of the class:
this._messageQueue = MsmqHelper.InitializeQueue();
Not that it really matters, but for completeness, here is where the queue is used:
this._messageQueue.Send(workflowCreated);
And here are the Dispose methods:
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing == false) { return; }
MsmqHelper.DisposeQueue(this._messageQueue);
}
And this is the code in the helper class that actually calls Dispose():
public static void DisposeQueue(MessageQueue messageQueue)
{
if (messageQueue != null)
{
messageQueue.Close();
messageQueue.Dispose();
messageQueue = null;
}
}
Where is it possible for the queue to be disposed more than once in this situation?
** Edit **
I thought it would be nice to add my comments, in the conversation below, here. It's a good summary, along with the accepted answer:
I think I get it now. The messageQueue method parameter has nothing to do with the original (this._messageQueue) reference to the object. So checking messageQueue for null, and setting it to null, does no good. The caller could still pass in its variable (this._messageQueue) even after being disposed. Hence, being able to be disposed more than once.
By the way, even setting the caller's variable (this._messageQueue) to null, in the calling method, doesn't help. The problem exists solely in MsmqHelper.DisposeQueue(). So the answer is to pass by ref or simply don't call DisposeQueue() and do it all in the calling method.
** Edit 2 **
After trying this, I get the same error. I simply don't get it.
public static void DisposeQueue(ref MessageQueue messageQueue)
{
if (messageQueue == null) { return; }
messageQueue.Close();
messageQueue.Dispose();
messageQueue = null;
}
** Edit 3 -- Bug? **
I'm starting to think that this may be a bug. If I comment messageQueue.Dispose(), the error goes away. HOWEVER, I can call messageQueue.Close() and messageQueue.Dispose() together in the calling method. Go figure. I think I'm just going to make these same calls from the calling methods, or only call Close() or Dispose() instead of both.
Close frees all resources of the MessageQueue object. See the documentation here. The error is most likely generated in CA because it sees that the execution path of Close also calls Dispose.
From the documentation:
public void ReceiveMessage()
{
// Connect to the a on the local computer.
MessageQueue myQueue = new MessageQueue(".\\myQueue");
// Set the formatter to indicate body contains an Order.
myQueue.Formatter = new XmlMessageFormatter(new Type[]
{typeof(String)});
try
{
// Receive and format the message.
Message myMessage1 = myQueue.Receive();
Message myMessage2 = myQueue.Receive();
}
catch (MessageQueueException)
{
// Handle sources of any MessageQueueException.
}
// Catch other exceptions as necessary.
finally
{
// Free resources.
myQueue.Close();
}
return;
}
Close apparently will release the resources but will allow the component to reacquire them if they haven't been collected yet. It might be more prudent to open the MessageQueue object, use it, and then close it within the same call rather than open it for a period of time and closing it later because connection caching removes the overhead of opening the MessageQueue in repeated calls.
*UPDATE*
It appears that CA treats CA2202 differently for member fields versus passing the disposable object to a method, even if that method is private to the class. Regardless, according to the documentation, you should only have to call Close() or Dispose() but not both. I recommend however changing your design so that you create, use, and then close the MessageQueue object all within the scope of your message operations like the example from the documentation example demonstrates above.
Yes. This can dispose the object multiple times:
The value that this._messageQueue evaluates to does not change after invoking MsmqHelper.DisposeQueue(this._messageQueue).
Only the local parameter (named messageQueue) was assigned the value null in the DisposeQueue method. Thus the "null guard" fails to correctly guard subsequent times around. (This is because C#'s default behavior is Call-By-Value: please see the link to understand what this means in context of "passing the value of a reference to an object".)
Either take in ref or assign this._messageQueue = null in the caller.
If MessageQueue class implements IDisposable iterface, then there is no point to use Dispose method explicitly and Close() method, because in all such classes Close() method is usually is not an iterface method but rather a class method. Typically, in Dispose method all correct impementation should call Close() mehod before release managed/unmanaged resources.
Again, by impelmenting external static helper, you break the Disposable pattern. It's not the correct way to control lifetime of the object; You don't need to mess up with Disposable pattern, you can simply use it
And your code might be simplified like this:
// 1. Use static class. By the agreement, all helper classes should be static to avoid
// IDisposable inheritance, in example
public static class MsmqHelper//: IDisposable
{
//private MessageQueue _messageQueue;
//public MessageQueueHelper(bool workflowCreated)
//{
// this._messageQueue = MsmqHelper.InitializeQueue();
// this._messageQueue.Send(workflowCreated);
//}
public static SendMessage(object workflowCreated)
{
// 2. If static method in static class does not takes parameters,
// I might be better to to implicitly call the constructor?
// using(MessageQueue msmsq = MsmqHelper.InitializeQueue())
using(MessageQueue msmsq = new MessageQueue())
{
msmq.Send(workflowCreated);
msmq.Close();
// MsmqHelper.DisposeQueue(msmq);
// 3. You should explicitly call Close object to immediately release
// unmanaged resources, while managed ones will be released
// at next GC rounds, as soon as possible
}
}
//private MessageQueue _messageQueue;
//public void Dispose()
//{
// Dispose(true);
// GC.SuppressFinalize(this);
//}
//private void Dispose(bool disposing)
//{
// if (disposing == false) { return; }
//
// MsmqHelper.DisposeQueue(this._messageQueue);
//}
//public static void DisposeQueue(MessageQueue messageQueue)
//{
// if (messageQueue != null)
// {
// messageQueue.Close();
// messageQueue.Dispose();
// messageQueue = null;
// }
//}
}