Created
June 3, 2020 06:11
-
-
Save xbotter/68c5db57ee635b22a03fed037957d8cd to your computer and use it in GitHub Desktop.
C# DelayTimer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface ITimerDataSource | |
{ | |
TimerTask LastTask(); | |
void RemoveTask(string taskid); | |
void Insert(TimerTask task); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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