Extra Variables
#region Extra Thread Timing Information
DateTime _runTimeOfDay = DateTime.MinValue;
string _runTimeOfDayString = "";
DateTime _nextRunTime;
DateTime _lastRunTime;
bool _runOnStartUp = false;
#endregion
Updated Functions
internal TaskThread(XmlNode node)
{
this._tasks = new Dictionary<string, Task>();
this._seconds = 10 * 60;
this._isRunning = false;
bool _cfgSeconds = (node.Attributes["seconds"] != null);
bool _cfgDays = (node.Attributes["days"] != null);
bool _cfgTime = (node.Attributes["time"] != null);
bool _cfgRunImmediately = (node.Attributes["runonstartup"] != null);
if (_cfgSeconds) // Original Task Behavior
{
if ((node.Attributes["seconds"] != null) && !int.TryParse(node.Attributes["seconds"].Value, out this._seconds))
{
this._seconds = 10 * 60;
}
// Since seconds are setup, no need to setup the rest
return;
}
// Setup days if available ...
if (_cfgDays && !int.TryParse(node.Attributes["days"].Value, out this._days)) this._days = 0;
// If the task thread needs to run at a specific time of day, set that up.
if (_cfgTime)
{
_runTimeOfDayString = node.Attributes["time"].Value;
if (!DateTime.TryParse(node.Attributes["time"].Value, out this._runTimeOfDay)) this._runTimeOfDay = DateTime.MinValue;
}
// If we dont want to wait the initial time for threading, eg. a specific time of day ... we want to run it at the soonest possible time.
// not the next possible time.
_runOnStartUp = node.Attributes["runonstartup"].Value == "true";
}
private void TimerHandler(object state)
{
this._timer.Change(-1, -1);
this.Run();
this._lastRunTime = DateTime.Now;
this._timer.Change(this.Interval, this.Interval);
}
/// <summary>
/// Gets the interval at which to run the tasks
/// </summary>
public int Interval
{
get
{
return _getCalculatedInterval();
}
}
New Functions
private int _getCalculatedInterval()
{
#region If only days are set return the calculated milliseconds
// If we are setup to run in intervals of days, calculate the days out.
if (this._days > 0 && this._runTimeOfDay == DateTime.MinValue)
{
if (_runOnStartUp)
{
_runOnStartUp = false;
return 1;
}
else
{
return _days * 24 * 60 * 60 * 1000; // Days * Hours * Min * Sec
}
}
#endregion
#region If the time of day is set we return the calculated the milliseconds
// If we are setup to run at a specific time of day, calculate the duration to the next runtime
if (this._runTimeOfDay != DateTime.MinValue)
{
_nextRunTime = DateTime.Now;
// Convert the next runtime into an actual date/time -> This will be set to today, at X time.
DateTime.TryParse(this._runTimeOfDayString, out _nextRunTime);
#region Add Days
// If we have days setup, use add the number of days to the next run time
if (!_runOnStartUp)
{
// Add X days, or 1 by default
if (this._days > 0) _nextRunTime = _nextRunTime.AddDays(this._days);
if (this._nextRunTime < DateTime.Now) _nextRunTime = _nextRunTime.AddDays(1);
}
#endregion
#region Check to see if the run on startup needs days added to it.
// In this case, we are are making sure that a daily interval
if (_runOnStartUp)
{
_runOnStartUp = false;
if (this._nextRunTime < DateTime.Now)
{
// Add X days, or 1 by default
if (this._days > 0) _nextRunTime = _nextRunTime.AddDays(this._days);
else _nextRunTime = _nextRunTime.AddDays(1);
}
}
#endregion
// Calculate the interval until the next run
TimeSpan futureDiff = new TimeSpan(this._nextRunTime.Ticks - DateTime.Now.Ticks);
// make sure it is greater than 1, just incase we ate up a few thousand ticks calculating and checking.
// ... or the machine is being hit pretty hard
return futureDiff.TotalMilliseconds > 0 ? (int)futureDiff.TotalMilliseconds : 1;
}
#endregion
// Base Case
return _seconds * 1000;
}
public DateTime GetNextRunTime()
{
return DateTime.Now.AddMilliseconds(this.Interval);
}
public TimeSpan GetNextInterval()
{
return new TimeSpan(0, 0, 0, 0, this.Interval);
}
Example Use of New Functionality
<ScheduleTasks>
<Thread days="5">
<task />
</Thread>
<Thread time="12:00:00 AM">
<task />
</Thread>
<Thread days="1" time="12:00:00 PM" runonstartup="true">
<task />
</Thread>
</ScheduleTasks>
First Question: Does the code look ok? It is running ok for me, but want a second opinion ... maybe a little bit of optimization
Second Question: If I were to release a derivative work, that uses some nopCommerce code, what are the restrictions?