Skip to content

Instantly share code, notes, and snippets.

@xbotter
Created June 3, 2020 06:11
Show Gist options
  • Save xbotter/68c5db57ee635b22a03fed037957d8cd to your computer and use it in GitHub Desktop.
Save xbotter/68c5db57ee635b22a03fed037957d8cd to your computer and use it in GitHub Desktop.
C# DelayTimer
public interface ITimerDataSource
{
TimerTask LastTask();
void RemoveTask(string taskid);
void Insert(TimerTask task);
}
public class TimerTask
{
public string TaskId { get; set; }
public long TriggerTime { get; set; }
public string EventName { get; set; }
public string Argements { get; set; }
public bool AllowDelayed { get; set; } = true;
}
public class TimerTrigger
{
private ITimerDataSource _db { get; set; }
private CancellationTokenSource _cancelSource { get; set; }
private Task _task { get; set; }
private Action<string, string> callback { get; set; }
private volatile int _lock = 0;
public int AllowDelaySeconds { get; set; } = 5;
public TimerTrigger(ITimerDataSource db)
{
this._db = db;
}
private void WaitTask()
{
if(0 == Interlocked.Exchange(ref _lock, 1)) {
if (_task?.Status == TaskStatus.Running)
{
return;
}
_cancelSource = new CancellationTokenSource();
_task = Task.Run(async () =>
{
var t = _db.LastTask();
var n = DateTime.Now;
if (t == null) return;
if (t.TriggerTime > n.Ticks)
{
var delay = new TimeSpan(t.TriggerTime - n.Ticks);
await Task.Delay(delay);
}
_db.RemoveTask(t.TaskId);
new Task(() => DispatchTask(t)).Start();
}, _cancelSource.Token);
Interlocked.Exchange(ref _lock, 0);
}
}
private void DispatchTask(TimerTask task)
{
WaitTask();
if (task.TriggerTime < DateTime.Now.AddSeconds(-AllowDelaySeconds).Ticks)
{
if (!task.AllowDelayed)
{
return;
}
}
callback?.Invoke(task.EventName, task.Argements);
}
public void Register(Action<string, string> action)
{
callback = action;
}
public void Start()
{
WaitTask();
}
public void InsertTask(TimerTask task)
{
if(task.TriggerTime < DateTime.Now.AddSeconds(AllowDelaySeconds).Ticks)
{
if (task.AllowDelayed)
{
callback?.Invoke(task.EventName, task.Argements);
return;
}
}
_db.Insert(task);
_cancelSource?.Cancel();
WaitTask();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment