feat: timer rescheduling, abstract scheduled action, datetime and dayofweek extensions

This commit is contained in:
Jeffery Thompson
2018-07-12 13:33:02 -04:00
parent 928f8e5e04
commit 465ac7c42c
6 changed files with 123 additions and 13 deletions

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq;
namespace ICD.Common.Utils.Extensions namespace ICD.Common.Utils.Extensions
{ {
@@ -28,5 +29,22 @@ namespace ICD.Common.Utils.Extensions
// Todo - Better handle different cultures // Todo - Better handle different cultures
return extends.ToString("HH:mm:ss:fff"); return extends.ToString("HH:mm:ss:fff");
} }
/// <summary>
/// Returns the closest DateTime to the target time that is greater than the target time
/// </summary>
/// <param name="target"></param>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static DateTime? NextEarliestTime(this DateTime target, params DateTime[] times)
{
if (times.Length == 0)
return null;
DateTime[] orderedTimes = times.OrderBy(dt => dt).ToArray();
var time = orderedTimes.FirstOrDefault(dt => target < dt);
return time == default(DateTime) ? (DateTime?) null : time;
}
} }
} }

View File

@@ -0,0 +1,17 @@
using System;
namespace ICD.Common.Utils.Extensions
{
public static class DayOfWeekExtensions
{
public static bool IsWeekday(this DayOfWeek day)
{
return !IsWeekend(day);
}
public static bool IsWeekend(this DayOfWeek day)
{
return day == DayOfWeek.Saturday || day == DayOfWeek.Sunday;
}
}
}

View File

@@ -113,6 +113,7 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RecursionUtils.cs" /> <Compile Include="RecursionUtils.cs" />
<Compile Include="ReprBuilder.cs" /> <Compile Include="ReprBuilder.cs" />
<Compile Include="Services\Scheduler\AbstactScheduledAction.cs" />
<Compile Include="Services\Scheduler\ActionSchedulerService.cs" /> <Compile Include="Services\Scheduler\ActionSchedulerService.cs" />
<Compile Include="Services\Scheduler\IActionSchedulerService.cs" /> <Compile Include="Services\Scheduler\IActionSchedulerService.cs" />
<Compile Include="Services\Scheduler\IScheduledAction.cs" /> <Compile Include="Services\Scheduler\IScheduledAction.cs" />

View File

@@ -0,0 +1,43 @@
using System;
using ICD.Common.Utils.EventArguments;
using ICD.Common.Utils.Extensions;
namespace ICD.Common.Utils.Services.Scheduler
{
public abstract class AbstractScheduledAction : IScheduledAction
{
public event EventHandler OnScheduledRunTimeChanged;
private DateTime? m_NextRunTime;
public DateTime? NextRunTime
{
get { return m_NextRunTime; }
private set
{
if (m_NextRunTime == value)
return;
m_NextRunTime = value;
OnScheduledRunTimeChanged.Raise(this);
}
}
public void Run()
{
RunFinal();
NextRunTime = UpdateRunTime();
}
/// <summary>
/// Runs when the action has hit its scheduled time
/// </summary>
public abstract void RunFinal();
/// <summary>
/// Runs after RunFinal in order to set the next run time of this action
/// </summary>
public abstract DateTime? UpdateRunTime();
}
}

View File

@@ -24,16 +24,10 @@ namespace ICD.Common.Utils.Services.Scheduler
public void Dispose() public void Dispose()
{ {
foreach (IScheduledAction action in m_Actions) Clear();
{
Unsubscribe(action);
IDisposable disposable = action as IDisposable; m_Timer.Stop();
if (disposable != null) m_Timer.Dispose();
disposable.Dispose();
}
m_Actions.Clear();
} }
#region Methods #region Methods
@@ -50,6 +44,8 @@ namespace ICD.Common.Utils.Services.Scheduler
{ {
m_CriticalSection.Leave(); m_CriticalSection.Leave();
} }
RescheduleTimer();
} }
public void Remove(IScheduledAction action) public void Remove(IScheduledAction action)
@@ -64,6 +60,28 @@ namespace ICD.Common.Utils.Services.Scheduler
{ {
m_CriticalSection.Leave(); m_CriticalSection.Leave();
} }
RescheduleTimer();
}
public void Clear()
{
m_CriticalSection.Enter();
try
{
foreach (IScheduledAction action in m_Actions)
{
Unsubscribe(action);
}
m_Actions.Clear();
}
finally
{
m_CriticalSection.Leave();
}
RescheduleTimer();
} }
public override string ToString() public override string ToString()
@@ -105,15 +123,25 @@ namespace ICD.Common.Utils.Services.Scheduler
} }
} }
RescheduleTimer();
}
private void RescheduleTimer()
{
// enter again to check the closest next run time // enter again to check the closest next run time
m_CriticalSection.Enter(); m_CriticalSection.Enter();
try try
{ {
var action = m_Actions.FirstOrDefault(); var action = m_Actions.FirstOrDefault(a => a.NextRunTime != null);
if (action == null) if (action == null || action.NextRunTime == null)
{
m_Timer.Stop();
return; return;
}
m_Timer.Reset((long)(DateTime.Now - action.NextRunTime).TotalMilliseconds); long msToNextAction = (long)(DateTime.Now - action.NextRunTime.Value).TotalMilliseconds;
long timerDueTime = Math.Min(msToNextAction, MAX_TIMER_INTERVAL);
m_Timer.Reset(timerDueTime);
} }
finally finally
{ {
@@ -169,6 +197,8 @@ namespace ICD.Common.Utils.Services.Scheduler
{ {
m_CriticalSection.Leave(); m_CriticalSection.Leave();
} }
RescheduleTimer();
} }
#endregion #endregion

View File

@@ -1,4 +1,5 @@
using System; using System;
using ICD.Common.Utils.EventArguments;
namespace ICD.Common.Utils.Services.Scheduler namespace ICD.Common.Utils.Services.Scheduler
{ {
@@ -12,7 +13,7 @@ namespace ICD.Common.Utils.Services.Scheduler
/// <summary> /// <summary>
/// Gets the next time this action should be run /// Gets the next time this action should be run
/// </summary> /// </summary>
DateTime NextRunTime { get; } DateTime? NextRunTime { get; }
void Run(); void Run();
} }