I have an object and I want to delay an operation. I made two different implementation for this. The first one uses System.Threading.Timer to delay my operation while the second one uses a static thread and an expiration date. Personnaly, I prefer the first method, but I was wandering if there’s any overhead for using a Timer rather than a managed Thread.
First implementation :
class ThingWithDelayedClose
{
private Action<ThingWithDelayedClose> _closeCallback;
public ThingWithDelayedClose(string key, Action<ThingWithDelayedClose> closeCallback)
{
this.Key = key;
_closeCallback = closeCallback;
Console.WriteLine("Object created: " + this.Key);
}
public string Key { get; private set; }
public void RequestClose()
{
Console.WriteLine("Close requested: " + this.Key);
dynamic state = new ExpandoObject();
state.Timer = new Timer(new TimerCallback(this.TimerCallback), state, 2000, Timeout.Infinite);
}
private void TimerCallback(dynamic state)
{
using ((Timer)state.Timer)
{
_closeCallback(this);
Console.WriteLine("Object closed: " + this.Key);
}
}
}
Second implementation :
class ThingWithDelayedClose
{
static List<ThingWithDelayedClose> s_instances;
static ThingWithDelayedClose()
{
s_instances = new List<ThingWithDelayedClose>();
new Thread(() =>
{
// I know that I would need to change this in a real world app
while (true)
{
lock (s_instances)
{
var now = DateTime.Now;
var removeList = new List<ThingWithDelayedClose>();
foreach (var instance in s_instances)
{
if (instance._closedTime <= now)
{
instance.Close();
removeList.Add(instance);
}
}
removeList.ForEach(p => s_instances.Remove(p));
}
Thread.Sleep(1000);
}
}).Start();
}
private DateTime _closedTime = DateTime.MaxValue;
private Action<ThingWithDelayedClose> _closeCallback;
public ThingWithDelayedClose(string key, Action<ThingWithDelayedClose> closeCallback)
{
this.Key = key;
_closeCallback = closeCallback;
Console.WriteLine("Object created: " + this.Key);
lock (s_instances)
{
s_instances.Add(this);
}
}
public string Key { get; private set; }
public void RequestClose()
{
Console.WriteLine("Close requested: " + this.Key);
_closedTime = DateTime.Now.Add(TimeSpan.FromSeconds(2.0d));
}
private void Close()
{
_closeCallback(this);
Console.WriteLine("Object closed: " + this.Key);
}
}
Using a timer is substantially cheaper than spinning up a new thread.
Depending on what you’re trying to accomplish, you can probably make it even faster (and simpler and safer) by using one of the built-in synchronization primitives in
System.Threading.