private void OnTimerExecute(object context) { // this list must never change or be made public // if that ever changes, then we'll need to make an object used for locks. lock (mTimerQueueData) { // loop through the list and find the timers data that all need to fire now // schedule them in order for (int i = mTimerQueueData.Count - 1; i >= 0; --i) { TimerQueueData data = mTimerQueueData[i]; DateTime now = DateTime.Now; if (data.TargetTime <= now) { mDispatchQueue.DispatchAsync(data.Context, data.Work); mTimerQueueData.RemoveAt(i); } else { mTimer.Change(data.TargetTime - now, Timeout.InfiniteTimeSpan); break; } } } }
public void DispatchAfter(DateTime when, object?context, WaitCallback work) { if (work == null) { throw new ArgumentNullException("work"); } TimerQueueData data = new TimerQueueData() { TargetTime = when, Work = work, Context = context }; // boxed "data" but ... I don't see an alternative mDispatcher.QueueWorkItem(mScheduleWorkForExecutionCallback, data); }
private void OnScheduleWorkForExecution(object context) { TimerQueueData data = (TimerQueueData)context; // this list must never change or be made public // if that ever changes, then we'll need to make an object used for locks. lock (mTimerQueueData) { // insert into the list sorted by TargetTime (earlier TargetTime is at the end of the list) var index = mTimerQueueData.BinarySearch(data, mTimerQueueDataComparer); if (index < 0) { index = ~index; } mTimerQueueData.Insert(index, data); DateTime earliestTarget = mTimerQueueData.Last().TargetTime; if (data.TargetTime < earliestTarget || mTimerQueueData.Count == 1) { mTimer.Change(earliestTarget - DateTime.Now, Timeout.InfiniteTimeSpan); } } }