There is a class in my project called DataParse. I am making multiple connections with Ethernet. Every time a new connection is opened I create a new class as follows. Also, there is one timer in this class.
public Dictionary<string, DataParse> classDictionary = new Dictionary<string, DataParse>();
Connect Code
string IpAddress = Ip.Text;
int Port = Convert.ToInt32(PortName.Text);
var IpPort = IpAddress + ":" + Port;
classDictionary.Add(IpPort, new DataParse());
classDictionary[IpPort].DataParseRun(IpPort);
I want to destroy the created class when the connection is closed. I want to destroy the timer with the class.
I implemented a method like this to destroy the class and I failed. He goes into the timer again.
Disconnected Code
private void Events_Disconnected(object sender, ClientDisconnectedEventArgs e)
{
classDictionary[e.IpPort].Dispose();
classDictionary.Remove(e.IpPort);
}
DataParse Code
public class DataParse : IDisposable
{
private bool _disposed = false;
private SafeHandle _safeHandle = new SafeFileHandle(IntPtr.Zero, true);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
// Dispose managed state (managed objects).
_safeHandle?.Dispose();
}
_disposed = true;
}
Timer timer;
byte[] moduleBuffer;
int writePtr;
string key;
public void DataParseRun(string IpPort)
{
moduleBuffer = new byte[50000];
writePtr = 0;
timer = new Timer(new TimerCallback(ParseTimer), null, TimeSpan.FromMilliseconds(1000), TimeSpan.FromMilliseconds(200));
key = IpPort;
}
void ParseTimer(object state)
{
var abc = key;
}
}
How can I destroy the class.
Try manually disposing the timer in the Dispose method. As far as I see the timer is never disposed.
timer.Dispose();
EDIT: Cant comment yet so Ill edit the answer. As far as I am aware you cant manually just remove your instance from memory.
It will be collected via Garbage Collector once all references to the instance are lost or unreachable - thus once you, as Trix in his answer advises, remove the instance from the Dictionary and dispose of the Timer and SafeHandle there should be nothing stopping the GC from collecting it. However when exactly this happens isn't up to you.
EDIT2: I would say so. You can try to test it by reading some huge file to String to take up 100MB and watch if the memory is let go once you dispose of everything. Apparently there is also a direct call you can make to the GC: GC.Collect() - if you call it from class I don't think it will collect that class but for testing you can call it after you dispose from the dictionary.
Related
This question already has answers here:
does nulling a System.Threading.Timer stop it?
(4 answers)
Closed 3 years ago.
Please see example below. Even though the reference to obj is set to null, the obj is not released and Obj_Elapsed continues printing i. Notice there is no reference to the timer out of the scope of the ObjectWithTimer constructor.
public class Program
{
public static void Main(string[] args)
{
object obj = new ObjectWithTimer();
Console.ReadLine();
Console.WriteLine("obj=null");
obj = null;
Console.ReadLine();
}
}
public class ObjectWithTimer
{
private int i;
public System.Timers.Timer t;
public ObjectWithTimer()
{
t = new System.Timers.Timer(5000);
t.Elapsed += Obj_Elapsed;
t.Enabled = true;
}
public void Obj_Elapsed(object sender, ElapsedEventArgs e)
{
i++;
Console.WriteLine(i);
}
}
Setting null in this instance and/or going out of scope is not good enough, The Timer has resources it's managing and needs to be cleaned up.
Since System.Timers.Timer Implements IDisposable, ideally so should your wrapper class
public class ObjectWithTimer : IDisposable
{
// Flag: Has Dispose already been called?
private bool _disposed = false;
private int _i;
public System.Timers.Timer Timer { get; }
public ObjectWithTimer()
{
Timer = new System.Timers.Timer(5000);
Timer.Elapsed += Obj_Elapsed;
Timer.Enabled = true;
}
public void Obj_Elapsed(object sender, ElapsedEventArgs e)
{
_i++;
Console.WriteLine(_i);
}
// Public implementation of Dispose pattern callable by consumers.
public void Dispose() =>Dispose(true);
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing) Timer?.Dispose();
_disposed = true;
}
}
You should in turn then also dispose of the wrapper called at some stage, and not just set it null, the easiest way to do that is with the using statement
Provides a convenient syntax that ensures the correct use of
IDisposable objects.
public static void Main(string[] args)
{
using(object obj = new ObjectWithTimer())
{
Console.ReadLine();
Console.WriteLine("obj=null");
}
Console.ReadLine();
}
Implementing a Dispose method
You implement a Dispose method to release unmanaged resources used by
your application. The .NET garbage collector does not allocate or
release unmanaged memory.
Note : This wasn't a complete tutorial on the IDisposable pattern, just an example. Please do your own research and diligence on this implementation
Additional Resouces
Do you need to dispose of objects and set them to null?
Why do we need Dispose() method on some object? Why doesn't the garbage collector do this work?
All, I am monitoring my outlook inbox for some emails and parses that based on the content. I do this by running a console application and triggering a timer as shown below. The problem is this gets garbage collected after some time and I have to restart the app manually. I cannot run this inside a windows service as I get some permission issues while calling the Outlook api. Please see my code below
I tried doing a GC.SuppressFinalize(), GC.KeepAlive() on the timer object but no avail.
class Program
{
private static System.Timers.Timer _timer = new System.Timers.Timer();
static void Main(string[] args)
{
_timer.Interval = 10000;
_timer.Start();
_timer.Elapsed += Timer_Elapsed1;
Console.ReadLine();
}
}
private static void Timer_Elapsed1(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
_timer.Stop();
AddNumbers(2, 2);
Console.WriteLine("The current time now is :{0}", DateTime.Now.ToString());
GC.SuppressFinalize(_timer);
_timer.Start();
}
catch (Exception ex)
{
_timer.Start();
Console.WriteLine("Timer restarted from exception");
}
finally
{
_timer.Start();
}
}
private static void AddNumbers(int x, int y)
{
var sum = x + y;
Console.WriteLine(sum);
}
In the scope of your example application your Timer is not being garbage collected so you must be getting another error. Also, please see my note and example below about GC.SuppressFinalize because what you're implying and what it does are two different things.
Loop instead of Timer
Just a suggestion: When using a Timer and the Elapsed event calls the timer to stop and then start again once complete this is a sign you need to have a simple loop running instead with a thread wait.
Since this is a console app and there are no other threads required I'll post a simple looping example that, IMO, would be more efficient and easier to manage.
using System;
using System.Threading;
namespace Question_Answer_Console_App
{
class Program
{
private const int SleepTimeMS = 10000;
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(new WaitCallback((state) =>
{
while (true)
{
Thread.Sleep(SleepTimeMS);
AddNumbers(2, 2);
Console.WriteLine("The current time now is :{0}", DateTime.Now.ToString());
}
}));
Console.Read();
}
private static void AddNumbers(int x, int y)
{
var sum = x + y;
Console.WriteLine(sum);
}
}
}
GC.SuppressFinalize Information
Also, GC.SuppressFinalize does not have anything to do with garbage collection; it just tells the garbage collector, that when collected, not to run the finalizer on the object (the destructor method in C#). This is useful when there are items already disposed and you don't want to reproduce the work... For example if you're object is IDisposable, and you place the Dispose method in the destructor, and the user properly disposes of it when it is being used then you may want to skip the destructor. Here's an example of using GC.SuppressFinalize properly.
public class SomethingDisposable : IDisposable
{
public void Dispose()
{
//Dispose of some unmanaged resources or something.
GC.SuppressFinalize(this); //We can safely skip the Destructor method (Finalizer)
}
~SomethingDisposable() => Dispose(); //Just incase the object is garbage collected and never properly disposed.
}
GC.SuppressFinalize Example
And just for show here's a console app that illustrates the GC.SuppressFinalize in work. I make 2 IDisposable objects. The first I actually dispose of properly with a using statement and the second I don't. Once they are out of scope they are up for garbage collection. I intentionally call the garbage collector and wait for all finalizers to be called so that we can immediately see results.
Notice the disposed object DOES NOT call the finalizer and the object that was not disposed does (which in turn calls dispose... which is the proper way to implement it.)
using System;
namespace Question_Answer_Console_App
{
class Program
{
private const string DisposableTestId = "Disposable-Test";
private const string FinalizingTestId = "Finalizing-Test";
static void Main(string[] args)
{
TestDisposing();
Console.WriteLine();
TestFinalizing();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.Read();
}
private static void TestDisposing()
{
using (var disposingTest = new TestSuppressFinalize(DisposableTestId))
PrintTesting(disposingTest);
}
private static void TestFinalizing()
{
var finalizingTest = new TestSuppressFinalize(FinalizingTestId);
PrintTesting(finalizingTest);
}
private static void PrintTesting(TestSuppressFinalize finalizingTest)
=> Console.WriteLine($"Testing {finalizingTest.TestId.ToString()}");
}
public class TestSuppressFinalize : IDisposable
{
public TestSuppressFinalize(string testId) => TestId = testId;
public string TestId { get; }
public void Dispose()
{
Console.WriteLine($"Disposed {TestId.ToString()}");
GC.SuppressFinalize(this);
}
~TestSuppressFinalize()
{
Console.WriteLine($"Finalized {TestId.ToString()}");
Dispose();
}
}
}
Output:
Testing Disposable-Test
Disposed Disposable-Test
Testing Finalizing-Test
Finalized Finalizing-Test
Disposed Finalizing-Test
I create a simple addIn for Power point and this is the code
pp.Application ppApplication = new pp.Application();
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
ppApplication.PresentationOpen += new pp.EApplication_PresentationOpenEventHandler(ppApplication_PresentationOpen);
ppApplication.PresentationClose += new pp.EApplication_PresentationCloseEventHandler(ppApplication_PresentationClose);
}
void ppApplication_PresentationOpen(pp.Presentation Pres)
{
}
void ppApplication_PresentationClose(pp.Presentation Pres)
{
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(ppApplication);
}
Power point never close if ppApplication is global. I think global com object dose not release in this way. What should I do?
Following the recommendation in this post Proper way of releasing COM objects?
1) Declare & instantiate COM objects at the last moment possible.
2) ReleaseComObject(obj) for ALL objects, at the soonest moment possible.
3) Always ReleaseComObject in the opposite order of creation.
4) NEVER call GC.Collect() except when required for debugging.
You should call
pp.Application ppApplication = new pp.Application();
within Ribbon_Load
Also you are asymmetric in your COM Instantiation and Release - you instantiate on class initialize (i.e. as a = new() in the variable declaration) but release when the presentation is closed. Closing a presentation isn't the same as closing the application - the ribbon is probably still available, and this will come to bite you.
The last point is that you never unhook the events you've hooked into the COM object, you should at least be doing
ppApplication.PresentationOpen -= new pp.EApplication_PresentationOpenEventHandler(ppApplication_PresentationOpen);
ppApplication.PresentationClose -= new pp.EApplication_PresentationCloseEventHandler(ppApplication_PresentationClose);
to deallocate the event handlers, otherwise you have some undead references.
You should apply Dispose/Finalize pattern to free you unmanaged resource properly. This will guarantee that once your class will be disposed, all unmanaged class members (not global variables) would be released.
See https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx
using System;
using System.Runtime.InteropServices;
namespace PowerPointTestApp
{
class Program
{
static void Main(string[] args)
{
using (Container c = new Container())
{
Console.WriteLine("Opened..");
}
Console.WriteLine("Closed..");
}
}
public class Container: IDisposable
{
Microsoft.Office.Interop.PowerPoint.Application pp = new Microsoft.Office.Interop.PowerPoint.Application();
public Container()
{
pp.PresentationOpen += (pres)=>
{
//DoSomething
};
pp.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
pp.Quit();
Marshal.FinalReleaseComObject(pp);
}
}
~Container()
{
Dispose(false);
}
}
}
My question is simple, why GC can't figure it out that timer object in the main should be garbage collected along with the timer inside TestTimer and associated EventHandler?
Why am I continously getting console.Writeline output?
class Program
{
public static void Main()
{
TestTimer timer = new TestTimer();
timer = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadKey();
}
}
public class TestTimer
{
private Timer timer;
public TestTimer()
{
timer = new Timer(1000);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
private void timer_Elapsed(Object sender, ElapsedEventArgs args)
{
Console.Write("\n" + DateTime.Now);
}
}
Don't depend on the GC, use the Dispose pattern to properly dispose the TestTimer (which then should dispose the Timer).
However, what happens is that the timer keeps itself alive by getting a GC handle on itself. Read this blog post:
http://nitoprograms.blogspot.com/2011/07/systemthreadingtimer-constructor-and.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+blogspot%2FOlZtT+%28Nito+Programming%29
Why do you expect that an active timer can get collected in the first place? My expectation is that it acts as a GC root. Else the timer would stop working just because you don't have a reference anymore.
You are not disposing the timer after use. This is what is delaying its collection.
If your class contains objects which implement IDisposable (like the Timer does), it should also implement IDisposable.
public class TestTimer : IDisposable
{
private Timer timer;
public TestTimer()
{
timer = new Timer(1000);
...
}
#region IDisposable
public void Dispose()
{
Dispose(true);
}
volatile bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (disposing && !disposed)
{
timer.Dispose();
GC.SupressFinalize(this);
disposed = true;
}
}
~TestTimer() { Dispose(false); }
#endregion
}
Your main method should then look like this:
public static void Main()
{
using (TestTimer timer = new TestTimer())
{
// do something
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadKey();
}
Again, if your TestTimer is supposed to live longer than a scope of a single Main method, then the class which creates it and holds its reference should also implement IDisposable.
When you start a timer timer.Start() a new thread(s) will start at the background,
When you calling timer = null; you are not stopping the thread(s) that the timer used. The garbage collector will not kill or abort threads that are running no matter of the original object that create those threads.
It turns out that this state parameter (and the TimerCallback delegate) have an interesting effect on garbage collection: if neither of them reference the System.Threading.Timer object, it may be garbage collected, causing it to stop. This is because both the TimerCallback delegate and the state parameter are wrapped into a GCHandle. If neither of them reference the timer object, it may be eligible for GC, freeing the GCHandle from its finalizer.
See this thread for more details.
Recently, I was asked to implement a class as part of a selection process. I did the program as requested. However, I failed in the test. I am really curious to know what is wrong in my solution. Any help is much appreciated. The question and my solution are given below
Question:
Implement a thread safe class which fires an event every second from construction. There need to be a function for finding the seconds elapsed. This class has to implement IDisposable and any calls to seconds elapsed function after calling dispose should fail.
My solution:
namespace TimeCounter
{
public delegate void SecondsElapsedHandler(object o, EventArgs e);
/// <summary>
/// Summary description for SecondCounter
/// </summary>
public class SecondCounter : IDisposable
{
private volatile int nSecondsElapsed;
Timer myTimer;
private readonly object EventLock = new object();
private SecondsElapsedHandler secondsHandler;
public SecondCounter()
{
nSecondsElapsed = 0;
myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler(OneSecondElapsed);
myTimer.Interval = 1000;
myTimer.AutoReset = false;
myTimer.Start();
}
public void OneSecondElapsed(object source, ElapsedEventArgs e)
{
try
{
SecondsElapsedHandler handlerCopy;
lock (EventLock)
{
handlerCopy = secondsHandler;
nSecondsElapsed++;
}
if (secondsHandler != null)
{
secondsHandler(this, e);
}
}
catch (Exception exp)
{
Console.WriteLine("Exception thrown from SecondCounter OneSecondElapsed " + exp.Message);
}
finally
{
if (myTimer != null)
{
myTimer.Enabled = true;
}
}
}
public event SecondsElapsedHandler AnotherSecondElapsed
{
add
{
lock (EventLock)
{
secondsHandler += value;
}
}
remove
{
lock (EventLock)
{
secondsHandler -= value;
}
}
}
public int SecondsElapsed()
{
if (this.IsDisposed)
{
throw new ObjectDisposedException("SecondCounter");
}
return nSecondsElapsed;
}
private bool IsDisposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool Disposing)
{
if (!IsDisposed)
{
if (Disposing)
{
}
if (myTimer != null)
{
myTimer.Dispose();
}
}
secondsHandler = null;
IsDisposed = true;
}
~SecondCounter()
{
Dispose(false);
}
}
}
There are a few problems:
You might have been penalized for general Exception swallowing though that's not specifically related to threading issues.
There's a race condition on your timer.Dispose, as you could Dispose the timer before it is set Enabled again, resulting in an Exception.
You never set myTimer to null in Dispose.
You're accessing the managed class myTimer from the finalizer (disposing=false), which is a bad idea.
The explicit implementation of the event with locking is unnecessary. Delegates are immutable and adding/removing an event will never result in an invalid delegate state, though there can be race conditions if delegates are added/removed around the same time that the callback is fired. If you use the standard 'public event' declaration without an explicit backing private delegate, the synchronization will be handled automatically.
(minor point) If you're implementing the full Dispose pattern, it's customary to mark the Dispose(bool disposing) method as protected virtual, so that deriving classes can hook into the disposal mechanism. Better yet, mark your class sealed and you can eliminate the finalizer entirely.
Your finalizer is probably broken. It correctly passes false as the Disposing parameter. This should tell Dispose(bool) to avoid attempting to dispose other managed objects. But in that method you put:
if (Disposing)
{
}
if (myTimer != null)
{
myTimer.Dispose();
}
So you ignore the value of Disposing. This means that you call the timer's Dispose method from the finalizer thread, when that object may already have been finalized (if it has a finalizer, which it probably does). Finalizers run in an unpredictable order. It's generally recommended to not make calls to other GC-managed objects from a finalizer.
In fact, it's usually recommended that you don't write finalizers at all these days. The question didn't ask you to write one! It's unfortunate that most tutorials about IDisposable also talk about finalizers. They're different subjects.
You also catch Exception, the universal exception base class. This means you catch things like NullReferenceException. Not usually a good idea. You also log to the console, which is not worth much in a GUI or server-based application.
You can replace:
myTimer.Elapsed += new ElapsedEventHandler(OneSecondElapsed);
with:
myTimer.Elapsed += OneSecondElapsed;
Your variable naming is inconsistent. Refer to the Microsoft guidelines.