ln.threading/ln.threading/Timer.cs

129 lines
3.1 KiB
C#

using System;
using System.Threading;
namespace ln.threading
{
public delegate void ElapsedDelegate(PoolTimer timer);
public class PoolTimer : IDisposable
{
public event ElapsedDelegate Elapsed;
TimeSpan interval;
public TimeSpan Interval {
get => interval;
set {
if (value <= TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(value));
interval = value;
lock (this){
Monitor.Pulse(this);
}
}
}
DateTime nextStart;
public DateTime NextStart => nextStart;
bool canceled = true;
public bool IsActive {
get => !canceled;
private set {
lock (this)
{
if (value && canceled)
Start();
else if (!value && !canceled)
Stop();
}
}
}
public PoolTimer(TimeSpan interval)
{
Interval = interval;
}
public PoolTimer(double interval)
{
Interval = TimeSpan.FromSeconds(interval);
}
public PoolTimer(int interval)
{
Interval = TimeSpan.FromMilliseconds(interval);
}
public PoolTimer(TimeSpan interval, Action action) :this(action)
{
Interval = interval;
}
public PoolTimer(double interval, Action action) :this(action)
{
Interval = TimeSpan.FromSeconds(interval);
}
public PoolTimer(int interval, Action action) :this(action)
{
Interval = TimeSpan.FromMilliseconds(interval);
}
PoolTimer(Action action)
{
Elapsed += (t)=>action();
}
public void Start()
{
lock (this)
{
if (canceled){
canceled = false;
DynamicThreadPool.DefaultPool.Enqueue(TimerThread);
}
}
}
public void Stop()
{
lock (this)
{
if (!canceled)
{
canceled = true;
Monitor.Pulse(this);
}
}
}
void TimerThread()
{
lock (this)
{
nextStart = DateTime.Now + Interval;
DateTime now;
while (!canceled)
{
now = DateTime.Now;
if ((nextStart < now) || (!Monitor.Wait(this, nextStart - now) && !canceled))
{
DynamicThreadPool.DefaultPool.Enqueue(()=>Elapsed?.Invoke(this));
nextStart += Interval;
} else {
nextStart = DateTime.Now + Interval;
}
}
}
}
public void Dispose()
{
Stop();
}
}
}