How to start an object containing a timer in a new thread? - c#

How to start running an object containing a timer in a new thread?
I have the below code that I should probably change it:
class MemoryCleaner : IDisposable
{
private readonly static MemoryCleaner Instance = new MemoryCleaner();
private readonly Timer _memoryWatcher = new Timer(15 * 1000);
public Timer MemoryWatcher
{
get
{
return this._memoryWatcher;
}
}
public void Dispose()
{
_memoryWatcher.Elapsed -= memoryWatcher_Elapsed;
this._memoryWatcher.Stop();
}
private void memoryWatcher_Elapsed(object sender, ElapsedEventArgs e)
{
var currentProcess = Process.GetCurrentProcess();
var megaBytes = currentProcess.PrivateMemorySize64 / (1024 * 1024);
if (megaBytes > 100)
{
// force an immediate garbage collection to free some unused memory quickly; this is an expensive process!
GC.Collect();
}
}
internal static void Start()
{
// this should be created in a new thread
Instance.MemoryWatcher.Elapsed += Instance.memoryWatcher_Elapsed;
Instance.MemoryWatcher.Start();
GC.KeepAlive(Instance);
}
internal static void Stop()
{
Instance.Dispose();
}
}
I'd like to use it like:
MemoryCleaner.Start();
// my memory thirsty code which generates so much garbage, e.g. downloads a document then disposes it.
MemoryCleaner.Stop();
What it should do is that I should create a new thread then on that thread it should create a new instance of the MemoryCleaner object and start that object.
How would that be possible to do that?
Some background info:
Basically, what the code should do is that it should checke the memory used by the main process every 15 seconds and forces the garbage collection if memory usage exceeds 100MB since so many garbage will be created.
Hope the question is clear.
Thanks,

If you're creating a System.Threading.Timer or System.Timers.Timer it doesn't much matter which thread you create it on - unless you specify a synchronization object, the timer will fire on a thread-pool thread anyway. Why would you want to create a thread just for the creation part?
(I'm not at all sure that all of this is a good idea anyway, but that's a separate matter... You should also consider whether making a singleton implementation implement IDisposable is really sensible.)

Related

Am I implementing this buffer using a C# Timer correctly?

I have a service that subscribes to updates to a repository.
When an update message is received, the service needs to reload some data from the repository.
However many update messages can be received in a short period of time. So I want to create a buffer / time window, that will mean only one reload will happen for that period were many update messages arrived.
I've created a very rough outline:
class TestService
{
private Timer scheduledReloadTimer;
public void AttemptReload()
{
if (scheduledReloadTimer == null)
{
Console.WriteLine("Scheduling reload...");
scheduledReloadTimer = new Timer(Reload, null, 10000, Timeout.Infinite);
}
else
{
Console.WriteLine("Reload already scheduled for this period...");
}
}
private void Reload(object stateInfo)
{
scheduledReloadTimer.Dispose();
scheduledReloadTimer = null;
Console.WriteLine("Doing reload..");
}
}
Is using the null check on the Timer good enough to see if a reload has already been scheduled?
Am I disposing the Timer correctly?
Is there anything else I am missing here, especially around thread safety?
I've seen another stackoverflow answer that suggests using the Reactive Extensions to achieve this: https://stackoverflow.com/a/42887221/67357 but is that overkill?
You do have a potential thread-safety issue here. A quick fix would be to create a thread lock scope around the critical parts of your code, to ensure that while you're inspecting/creating and setting the timer variable, no other thread can get in there and start the same process in parallel:
class TestService
{
private Timer scheduledReloadTimer;
private object timerLock = new object();
public void AttemptReload()
{
lock (timerLock)
{
if (scheduledReloadTimer == null)
{
Console.WriteLine("Scheduling reload...");
scheduledReloadTimer = new Timer(Reload, null, 10000, Timeout.Infinite);
}
else
{
Console.WriteLine("Reload already scheduled for this period...");
}
}
}
private void Reload(object stateInfo)
{
lock (timerLock)
{
scheduledReloadTimer.Dispose();
scheduledReloadTimer = null;
}
Console.WriteLine("Doing reload..");
}
}
Reactive Extensions are a good way to deal with this throttling issue - as the code is already written for you.
Another approach might be to modify the AttemptReload call to simply reset the interval on the timer (if the reloadTimer != null), essentially pushing back the invocation of the timer event with each subsequent call to AttemptReload.
That way, the timer will definitely not fire until after the last call to AttemptReload + 10,000 milliseconds.

C# UserControl timer continues to tick after parent MFC CDialog destroyed [duplicate]

Preface: I know how to solve the problem. I want to know why it arises. Please read the question from top to bottom.
As we all (should) know, adding event handlers can cause memory leaks in C#. See Why and How to avoid Event Handler memory leaks?
On the other hand, objects often have similar or connected life cycles and deregistering event handlers is not necessary. Consider this example:
using System;
public class A
{
private readonly B b;
public A(B b)
{
this.b = b;
b.BEvent += b_BEvent;
}
private void b_BEvent(object sender, EventArgs e)
{
// NoOp
}
public event EventHandler AEvent;
}
public class B
{
private readonly A a;
public B()
{
a = new A(this);
a.AEvent += a_AEvent;
}
private void a_AEvent(object sender, EventArgs e)
{
// NoOp
}
public event EventHandler BEvent;
}
internal class Program
{
private static void Main(string[] args)
{
B b = new B();
WeakReference weakReference = new WeakReference(b);
b = null;
GC.Collect();
GC.WaitForPendingFinalizers();
bool stillAlive = weakReference.IsAlive; // == false
}
}
A and B reference each other implicitly via events, yet the GC can delete them (because it's not using reference counting, but mark-and-sweep).
But now consider this similar example:
using System;
using System.Timers;
public class C
{
private readonly Timer timer;
public C()
{
timer = new Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start(); // (*)
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// NoOp
}
}
internal class Program
{
private static void Main(string[] args)
{
C c = new C();
WeakReference weakReference = new WeakReference(c);
c = null;
GC.Collect();
GC.WaitForPendingFinalizers();
bool stillAlive = weakReference.IsAlive; // == true !
}
}
Why can the GC not delete the C object? Why does the Timer keep the object alive? Is the timer kept alive by some "hidden" reference of the timer mechanics (e.g. a static reference)?
(*) NB: If the timer is only created, not started, the issue does not occur. If it's started and later stopped, but the event handler is not deregistered, the issue persists.
The timer logic relies on an OS functionality. It is actually the OS that fires the event. OS in turn uses CPU interrupts to implement that.
The OS API, aka Win32, does not hold references to any objects of any kind. It holds memory addresses of functions which it has to call when a timer event happens. .NET GC has no way to track such "references". As a result a timer object could be collected without unsubscribing from the low-level event. It is a problem because OS would try to call it anyway and would crash with some weird memory access exception. That's why .NET Framework holds all such timer objects in the statically referenced object and removes them from that collection only when you unsubscribe.
If you look at the root of your object using SOS.dll you will get the next picture:
!GCRoot 022d23fc
HandleTable:
001813fc (pinned handle)
-> 032d1010 System.Object[]
-> 022d2528 System.Threading.TimerQueue
-> 022d249c System.Threading.TimerQueueTimer
-> 022d2440 System.Threading.TimerCallback
-> 022d2408 System.Timers.Timer
-> 022d2460 System.Timers.ElapsedEventHandler
-> 022d23fc TimerTest.C
Then if you look at the System.Threading.TimerQueue class in something like dotPeek, you will see that it is implemented as a singleton and it holds a collection of timers.
That's how it works. Unfortunately the MSDN documentation is not crystal clear about it. They just assumed that if it implements IDisposable then you should dispose it no question asked.
Is the timer kept alive by some "hidden" reference of the timer mechanics (e.g. a static reference)?
Yes. It is built in the CLR, you can see a trace of it when you use the Reference Source or a decompiler, the private "cookie" field in the Timer class. It is passed as the second argument to the System.Threading.Timer constructor that actually implements the timer, the "state" object.
The CLR keeps a list of enabled system timers and adds a reference to the state object to ensure it doesn't get garbage collected. Which in turn ensures that the Timer object doesn't get garbage collected as long as it is in the list.
So getting a System.Timers.Timer garbage collected requires that you call its Stop() method or set its Enabled property to false, same thing. Which cause the CLR to remove the system timer from the list of active timers. Which also removes the reference to the state object. Which then makes the timer object eligible for collection.
Clearly this is desirable behavior, you do not typically want to have a timer just disappear and stop ticking while it is active. Which will happen when you use a System.Threading.Timer, it stops calling its callback if you don't keep a reference to it, either explicitly or by using the state object.
I think this is related to the way that the Timer is implemented. When you call Timer.Start(), it sets Timer.Enabled = true. Look at the implementation of Timer.Enabled:
public bool Enabled
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get
{
return this.enabled;
}
set
{
if (base.DesignMode)
{
this.delayedEnable = value;
this.enabled = value;
}
else if (this.initializing)
{
this.delayedEnable = value;
}
else if (this.enabled != value)
{
if (!value)
{
if (this.timer != null)
{
this.cookie = null;
this.timer.Dispose();
this.timer = null;
}
this.enabled = value;
}
else
{
this.enabled = value;
if (this.timer == null)
{
if (this.disposed)
{
throw new ObjectDisposedException(base.GetType().Name);
}
int dueTime = (int) Math.Ceiling(this.interval);
this.cookie = new object();
this.timer = new Timer(this.callback, this.cookie, dueTime, this.autoReset ? dueTime : 0xffffffff);
}
else
{
this.UpdateTimer();
}
}
}
}
}
It looks like a new timer is created, with a cookie object passed to it (very odd!). Following that call path leads to some other complex code involving creating a TimerHolder and a TimerQueueTimer. I expect at some point a reference held outside the Timer itself is created, until such time as you call Timer.Stop() or Timer.Enabled = false.
This isn't a definitive answer, since none of the code I posted creates such a reference; but it's complicated enough down in the guts to lead me to suspect that something like that is happening.
If you have Reflector (or similar) have a look and you'll see what I mean. :)
Because Timer is still active. (Event handler is not removed for Timer.Elapsed).
If you want to properly dispose, Implement IDisposable interface, remove the event handler in the Dispose method, and use the using block or call the Dispose manually. The issue will not occur.
Example
public class C : IDisposable
{
...
void Dispose()
{
timer.Elapsed -= timer_elapsed;
}
}
And then
C c = new C();
WeakReference weakReference = new WeakReference(c);
c.Dispose();
c = null;
I think the problem arises from this line;
c = null;
In general, most developers think that making an object equal to null results in object to be deleted by garbage collector. But this is not the case; in fact only a reference to a memory location (where c object is created) is deleted; if there are any other references to the related memory location, object will not be marked for deletion. In this case, since Timer is referencing the related memory location, object will not be deleted by garbage collector.
Let's first talk about Threading.Timer. Internally, the timer will construct a TimerQueueTimer object using callback and state passed to Timer ctor (say new Threading.Timer(callback, state, xxx, xxx). The TimerQueueTimer will be added to a static list.
If callback method and state have no "this" info (say using static method for callback and null for state), then the Timer object can be GCed when no reference.
On the other hand, if a member method is used for callback, the delegate containing "this" will be stored in the static list mentioned above. So Timer object cannot be GCed since the "C" (in your example) object is still referenced.
Now let's back to System.Timers.Timer which internally wraps Threading.Timer. Note that when the former constructs the latter, a System.Timers.Timer member method is used, so System.Timers.Timer object cannot be GCed.

Timers and Garbage Collection

Say I have a class like this
class A
{
private B _objB
private Timer _timer; // Using System.Timers
public A(objB)
{
_objB = objB;
_timer = new Timer();
_timer.Interval = 1000;
_timer.Elapsed += SomeEvent;
}
public void Begin()
{
_timer.start();
}
public void End()
{
_timer.Dispose();
}
public void SomeEvent (object sender, ElapsedEventArgs e)
{
if (_objB.Condition())
{
// do something
}
else
{
_timer.Dispose();
}
}
}
Now somewhere else in my code in a different class I do this
public void SomeMethod(B objectB)
{
A objA = new A(objectB);
objA.Begin();
// do other stuff
// objA.End() can be called here but for this example it's not
}
I know that when I exit the scope of SomeMethod(), objA will won't be garbage collected because there is a timer event that keeps on firing. What I'm not sure about are the following:
1) When in SomeEvent, I hit the else condition and call _timer.Dispose(), this stops firing further events, but will this tell the GC that it can clean up the timer, and objA? In another words, am I causing any memory leaks?
2) Are there any race conditions that can cause exceptions? So like if I'm calling _timer.Dispose() and somehow have another timer event in queue, does entering that event causes any exceptions?
I'm just unsure if I'm doing right amount of cleaning up to avoid memory leaks.
Generally correct. When you dispose Timer, ObjA will be eligible for GC. In fact, garbage collector will collect it during its next garbage collection cycle.
Keep in mind that, It will not collect your object immediately after it becomes eligible for GC. Garbage collector uses its heuristic algorithm to to trigger garbage collection. It occurs only when there is a memory pressure. In fact when Gen0 or Large Object Heap about to overflow.
Possibly.. Have a look at here.
Callbacks can occur after the Dispose() method overload has been
called, because the timer queues callbacks for execution by thread
pool threads. You can use the Dispose(WaitHandle) method overload to
wait until all callbacks have completed.

Windows service with FileSystemWatcher and Timer - making sure everything gets disposed

I have created a C# Windows Service application that starts a FileSystemWatcher to monitor a directory for the creation of a file. When the file is found I instantiate a custom class that parses the file (CSV) and calls a web service with it's contents. The service is somewhat asynchronous and returns a unique number which must be used for subsequent calls to check its progress. In my process class I create a timer to continually check to see if the job is finished. I am disposeing and closeing my timer when I am done with it but I just want to make sure my class will be garbage collected and I will not have any memory leaks.
The code looks like this (snipped for brevity):
My main service class:
protected override void OnStart(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = "path";
watcher.Filter = "file";
watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.EnableRaisingEvents = true;
}
static void watcher_Created(object sender, FileSystemEventArgs e)
{
FileProcessor p = new FileProcessor();
p.Process(e.FullPath);
//Will this instance of p stick around until the timer within it is finished?
}
FileProcessor.cs
class FileProcessor
{
private System.Timers.Timer timer = new System.Timers.Timer();
private string id;
public FileProcessor()
{
timer.Elapsed += new ElapsedEventHandler(OnTimer);
timer.Enabled = false;
timer.AutoReset = true;
}
public void Process(string filename)
{
//Read file <snipped>
//Call web service and get id
id = CallWebService();
//Create a timer for 10 seconds and start it
timer.Interval = 10000;
timer.Enabled = true;
}
private bool IsFinished(string id)
{
//Call web service to see if job is finished, true if finished
//<snipped>
}
private void ProcessResults()
{
//Job is finished, process results
//Call cleanup method to dispose of timer
Cleanup();
}
private void OnTimer(object source, ElapsedEventArgs e)
{
if (!IsFinished(id))
{
//Keep timer running, check result again next timer event
return;
}
else
{
//Stop timer
timer.Stop();
//Process Results
ProcessResults(response);
}
}
private void Cleanup()
{
timer.Close();
timer.Dispose();
}
}
My question is should my instance of "p" stick around (not be GC'ed) until my timer is destroyed? Will it ever be destroyed? Does my FileProcessor class need to implement IDisposable so I can wrap it in a using block? I am not worried about this being single threaded because I only expect it to process one file per day and it should not take more than 10 minutes for the process to finish and return to watching for the next file to be created.
You are on the right track. FileSystemWatcher implements the Component class, which requires you to dispose it after use. Since this is the case, the correct approach would be to have your FileProcessor class implement IDisposable as you suggested.
Since you are going to have the FileProcessor object live for an extended period of time, you will not be able to use a using statement. This is because the object would attempt to get disposed before it was done with its work.
This being the case, I would implement an event on the FileProcessor to notify the consumer when processing is complete. When this is complete I would call the Dispose method on the FileProcessor object. The Dispose method should perform all cleanup required for that object - IE: timer, watcher, etc.
For your reference, this is a good article which lays out some guidelines for when and how to use the IDisposable interface. Also, as a good practice, you will want to wrap the calls in the consumer in try/catch blocks - you need to ensure that no matter what happens, you attempt to free the resources.

Single threaded timer

I wanted a timer with the following properties:
No matter how many times start is called, only one call back thread is ever running
The time spent in the call back function was ignored with regards to the interval. E.g if the interval is 100ms and the call back takes 4000ms to execute, the callback is called at 100ms, 4100ms etc.
I couldn't see anything available so wrote the following code. Is there a better way to do this?
/**
* Will ensure that only one thread is ever in the callback
*/
public class SingleThreadedTimer : Timer
{
protected static readonly object InstanceLock = new object();
//used to check whether timer has been disposed while in call back
protected bool running = false;
virtual new public void Start()
{
lock (InstanceLock)
{
this.AutoReset = false;
this.Elapsed -= new ElapsedEventHandler(SingleThreadedTimer_Elapsed);
this.Elapsed += new ElapsedEventHandler(SingleThreadedTimer_Elapsed);
this.running = true;
base.Start();
}
}
virtual public void SingleThreadedTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (InstanceLock)
{
DoSomethingCool();
//check if stopped while we were waiting for the lock,
//we don't want to restart if this is the case..
if (running)
{
this.Start();
}
}
}
virtual new public void Stop()
{
lock (InstanceLock)
{
running = false;
base.Stop();
}
}
}
Here's a quick example I just knocked up;
using System.Threading;
//...
public class TimerExample
{
private System.Threading.Timer m_objTimer;
private bool m_blnStarted;
private readonly int m_intTickMs = 1000;
private object m_objLockObject = new object();
public TimerExample()
{
//Create your timer object, but don't start anything yet
m_objTimer = new System.Threading.Timer(callback, m_objTimer, Timeout.Infinite, Timeout.Infinite);
}
public void Start()
{
if (!m_blnStarted)
{
lock (m_objLockObject)
{
if (!m_blnStarted) //double check after lock to be thread safe
{
m_blnStarted = true;
//Make it start in 'm_intTickMs' milliseconds,
//but don't auto callback when it's done (Timeout.Infinite)
m_objTimer.Change(m_intTickMs, Timeout.Infinite);
}
}
}
}
public void Stop()
{
lock (m_objLockObject)
{
m_blnStarted = false;
}
}
private void callback(object state)
{
System.Diagnostics.Debug.WriteLine("callback invoked");
//TODO: your code here
Thread.Sleep(4000);
//When your code has finished running, wait 'm_intTickMs' milliseconds
//and call the callback method again,
//but don't auto callback (Timeout.Infinite)
m_objTimer.Change(m_intTickMs, Timeout.Infinite);
}
}
The .NET Framework provides four timers. Two of these are general-purpose multithreaded
timers:
System.Threading.Timer
System.Timers.Timer
The other two are special-purpose single-threaded timers:
System.Windows.Forms.Timer (Windows Forms timer)
System.Windows.Threading.DispatcherTimer (WPF timer)
The last 2 are designed to eliminate thread-safety issues for WPF and Windows Forms applications.
For example, using WebBrowser inside a timer to capture screenshots from webpage needs to be single-threaded and gives an error at runtime if it is on another thread.
The single-thread timers have the following benefits
You can forget about thread safety.
A fresh Tick will never fire until the previous Tick has finished
processing.
You can update user interface elements and controls directly from
Tick event handling code, without calling Control.BeginInvoke or
Dispatcher.BeginIn voke.
and main disadvantage to note
One thread serves all timers—as well as the processing UI events.
Which means that the Tick event handler must execute quickly,
otherwise the user interface becomes unresponsive.
source: most are scraps from C# in a Nutshell book -> Chapter 22 -> Advanced threading -> Timers -> Single-Threaded Timers
For anyone who needs a single thread timer and wants the timer start to tick after task done.
System.Timers.Timer could do the trick without locking or [ThreadStatic]
System.Timers.Timer tmr;
void InitTimer(){
tmr = new System.Timers.Timer();
tmr.Interval = 300;
tmr.AutoReset = false;
tmr.Elapsed += OnElapsed;
}
void OnElapsed( object sender, System.Timers.ElapsedEventArgs e )
{
backgroundWorking();
// let timer start ticking
tmr.Enabled = true;
}
Credit to Alan N
source https://www.codeproject.com/Answers/405715/System-Timers-Timer-single-threaded-usage#answer2
Edit: spacing
Look at the [ThreadStatic] attribute and the .Net 4.0 ThreadLocal generic type. This will probably quickly give you a way to code this without messing with thread locking etc.
You could have a stack inside your time class, and you could implement a Monitor() method that returns a IDisposable, so you can use the timer like so:
using (_threadTimer.Monitor())
{
// do stuff
}
Have the timer-monitor pop the the interval timestamp off the stack during Dispose().
Manually coding all the locking and thread recognition is an option as has been mentioned. However, locking will influence the time used, most likely more than having to initialize an instance per thread using ThreadLocal
If you're interested, I might knock up an example later
Here is a simple PeriodicNonOverlappingTimer class, that provides just the requested features, and nothing more than that. This timer cannot be started and stopped on demand, and neither can have its interval changed. It just invokes the specified action periodically in a non overlapping manner, until the timer is disposed.
/// <summary>
/// Invokes an action on the ThreadPool at specified intervals, ensuring
/// that the invocations will not overlap, until the timer is disposed.
/// </summary>
public class PeriodicNonOverlappingTimer : IDisposable, IAsyncDisposable
{
private readonly System.Threading.Timer _timer;
public PeriodicNonOverlappingTimer(Action periodicAction,
TimeSpan dueTime, TimeSpan period)
{
// Arguments validation omitted
_timer = new(_ =>
{
var stopwatch = Stopwatch.StartNew();
periodicAction();
var nextDueTime = period - stopwatch.Elapsed;
if (nextDueTime < TimeSpan.Zero) nextDueTime = TimeSpan.Zero;
try { _timer.Change(nextDueTime, Timeout.InfiniteTimeSpan); }
catch (ObjectDisposedException) { } // Ignore this exception
});
_timer.Change(dueTime, Timeout.InfiniteTimeSpan);
}
public void Dispose() => _timer.DisposeAsync().AsTask().Wait();
public ValueTask DisposeAsync() => _timer.DisposeAsync();
}
Usage example. Shows how to create a non-overlapping timer that starts immediately, with a period of 10 seconds.
var timer = new PeriodicNonOverlappingTimer(() =>
{
DoSomethingCool();
}, TimeSpan.Zero, TimeSpan.FromSeconds(10));
//...
timer.Dispose(); // Stop the timer once and for all
In case the DoSomethingCool fails, the exception will be thrown on the ThreadPool, causing the process to crash. So you may want to add a try/catch block, and handle all the exceptions that may occur.
The Dispose is a potentially blocking method. If the periodicAction is currently running, the Dispose will block until the last invocation is completed.
If you don't want to wait for this to happen, you can do this instead:
_ = timer.DisposeAsync(); // Stop the timer without waiting it to finish

Categories

Resources