129 lines
3.1 KiB
C#
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();
|
|
}
|
|
}
|
|
} |