wasSharp

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 9  →  ?path2? @ 10
/Timers/Timer.cs
@@ -0,0 +1,114 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Threading;
using System.Threading.Tasks;
 
namespace wasSharp.Timers
{
public delegate void TimerCallback(object state);
 
public class Timer : IDisposable
{
private static readonly Task CompletedTask = Task.FromResult(false);
private readonly TimerCallback Callback;
private readonly object State;
private Task Delay;
private bool Disposed;
private int Period;
private CancellationTokenSource TokenSource;
 
public Timer(TimerCallback callback, object state, int dueTime, int period)
{
Callback = callback;
State = state;
Period = period;
Reset(dueTime);
}
 
public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
: this(callback, state, (int) dueTime.TotalMilliseconds, (int) period.TotalMilliseconds)
{
}
 
public Timer(TimerCallback callback) : this(callback, null, TimeSpan.Zero, TimeSpan.Zero)
{
}
 
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
 
~Timer()
{
Dispose(false);
}
 
private void Dispose(bool cleanUpManagedObjects)
{
if (cleanUpManagedObjects)
Cancel();
Disposed = true;
}
 
public void Change(int dueTime, int period)
{
Period = period;
Reset(dueTime);
}
 
public void Change(uint dueTime, int period)
{
Period = period;
Change((int) dueTime, period);
}
 
public void Change(TimeSpan dueTime, TimeSpan period)
{
Change((int) dueTime.TotalMilliseconds, (int) period.TotalMilliseconds);
}
 
private void Reset(int due)
{
Cancel();
if (due <= 0)
return;
TokenSource = new CancellationTokenSource();
Action tick = null;
tick = () =>
{
Task.Run(() => Callback(State));
if (Disposed)
return;
Delay = Period > 0 ? Task.Delay(Period, TokenSource.Token) : CompletedTask;
if (Delay.IsCompleted)
return;
Delay.ContinueWith(t => tick(), TokenSource.Token);
};
Delay = due > 0 ? Task.Delay(due, TokenSource.Token) : CompletedTask;
if (Delay.IsCompleted)
return;
Delay.ContinueWith(t => tick(), TokenSource.Token);
}
 
public void Stop()
{
Change(0, 0);
}
 
private void Cancel()
{
if (TokenSource == null)
return;
TokenSource.Cancel();
TokenSource.Dispose();
TokenSource = null;
}
}
}