protected void OnRunning()
{
SpinWait wait = new SpinWait();
while (true)
{
int state = m_state;
if (state == State.ScheduledToRun && Interlocked.CompareExchange(ref m_state, State.Running, State.ScheduledToRun) == State.ScheduledToRun)
{
break;
}
if (state == State.ScheduledToRunAfterDelay && Interlocked.CompareExchange(ref m_state, State.Running, State.ScheduledToRunAfterDelay) == State.ScheduledToRunAfterDelay)
{
break;
}
wait.SpinOnce();
}
wait.Reset();
m_runAgain = false;
m_runAgainAfterDelay = -1;
Thread.MemoryBarrier();
m_args.StartDisposalCallSuccessful = m_startDisposalCallSuccessful;
bool failedRun = !m_callback.TryInvoke(m_args);
if (m_args.ShouldDispose || failedRun)
{
InternalDispose_FromWorkerThread();
Interlocked.Exchange(ref m_state, State.Disposed);
return;
}
Interlocked.Exchange(ref m_state, State.AfterRunning); //Notifies that the RunAgain and RunAgainAfterDelay variables are going to be used
// to make decisions. Therefore, if setting these variables after this point, modifying the state machine will be
// necessary
if (m_runAgain)
{
Interlocked.Exchange(ref m_state, State.ScheduledToRun);
InternalStart_FromWorkerThread();
}
else if (m_runAgainAfterDelay >= 0)
{
InternalStart_FromWorkerThread(m_runAgainAfterDelay);
Interlocked.Exchange(ref m_state, State.ScheduledToRunAfterDelay);
}
else
{
InternalDoNothing_FromWorkerThread();
Interlocked.Exchange(ref m_state, State.NotRunning);
}
}