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); } }
protected void Shutdown() { if (m_ignoreShutdownHandler) { return; } //If the caller did not want to be notified on shutdown // or they did but the callback failed. // clear all callbacks and initiate a disposal. if (!m_disposeOnShutdown && !m_disposeAndWaitCallback.TryInvoke()) { m_callback.Clear(); m_disposeAndWaitCallback.Clear(); StartDisposal(); } }
private void Callback(T item) { m_remoteCallback.TryInvoke(item); }