internal async Task RunPendingEvent(PendingEvent ev)
{
var eventTime = ev.ScheduledTime;
var execLockTaken = false;
try
{
lock (_scheduleLock)
{
if (ev.RunId != _runId)
return;
// take execution lock
execLockTaken = Interlocked.CompareExchange(ref _execLocked, 1, 0) == 0;
if (execLockTaken)
PrevEvent = eventTime; // set this here while we're still in the schedule lock
}
if (execLockTaken)
{
try
{
if (Callback != null)
Callback(this, eventTime);
else
await AsyncCallback(this, eventTime).ConfigureAwait(false);
}
catch (Exception ex)
{
RaiseException(ex);
}
}
}
finally
{
if (execLockTaken)
_execLocked = 0; // release exec lock
}
// figure out the next time to run the schedule
lock (_scheduleLock)
{
if (ev.RunId != _runId)
return;
try
{
var next = Schedule.Next();
if (next <= eventTime)
next = Schedule.Next(eventTime);
NextEvent = next;
QueueNextEvent();
}
catch (Exception ex)
{
_runId++;
IsScheduleRunning = false;
RaiseException(new ScheduleCrashException("Schtick Schedule has been terminated because the next valid time could not be found.", this, ex));
}
}
}