微软关于CancellationTokenSource的介绍很简单,其实CancellationTokenSource的使用也很简单,但是实现就不是那么简单了,我们首先来看看CancellationTokenSource的实现:
public class CancellationTokenSource : IDisposable { private const int CANNOT_BE_CANCELED = 0; private const int NOT_CANCELED = 1; private const int NOTIFYING = 2; private const int NOTIFYINGCOMPLETE = 3; private volatile int m_state; private static readonly Action<object> s_LinkedTokenCancelDelegate = new Action<object>(LinkedTokenCancelDelegate); private static readonly int s_nLists = (PlatformHelper.ProcessorCount > 24) ? 24 : PlatformHelper.ProcessorCount; private volatile CancellationCallbackInfo m_executingCallback; private volatile SparselyPopulatedArray<CancellationCallbackInfo>[] m_registeredCallbacksLists; private static readonly TimerCallback s_timerCallback = new TimerCallback(TimerCallbackLogic); private volatile Timer m_timer; public CancellationTokenSource() { m_state = NOT_CANCELED; } //Constructs a CancellationTokenSource that will be canceled after a specified time span. public CancellationTokenSource(Int32 millisecondsDelay) { if (millisecondsDelay < -1) { throw new ArgumentOutOfRangeException("millisecondsDelay"); } InitializeWithTimer(millisecondsDelay); } private void InitializeWithTimer(Int32 millisecondsDelay) { m_state = NOT_CANCELED; m_timer = new Timer(s_timerCallback, this, millisecondsDelay, -1); } private static void TimerCallbackLogic(object obj) { CancellationTokenSource cts = (CancellationTokenSource)obj; if (!cts.IsDisposed) { try { cts.Cancel(); // will take care of disposing of m_timer } catch (ObjectDisposedException) { if (!cts.IsDisposed) throw; } } } public void Cancel() { Cancel(false); } public void Cancel(bool throwOnFirstException) { ThrowIfDisposed(); NotifyCancellation(throwOnFirstException); } public void CancelAfter(Int32 millisecondsDelay) { ThrowIfDisposed(); if (millisecondsDelay < -1) { throw new ArgumentOutOfRangeException("millisecondsDelay"); } if (IsCancellationRequested) return; if (m_timer == null) { Timer newTimer = new Timer(s_timerCallback, this, -1, -1); if (Interlocked.CompareExchange(ref m_timer, newTimer, null) != null) { newTimer.Dispose(); } } // It is possible that m_timer has already been disposed, so we must do // the following in a try/catch block. try { m_timer.Change(millisecondsDelay, -1); } catch (ObjectDisposedException) { } } private void NotifyCancellation(bool throwOnFirstException) { if (IsCancellationRequested) return; // If we're the first to signal cancellation, do the main extra work. if (Interlocked.CompareExchange(ref m_state, NOTIFYING, NOT_CANCELED) == NOT_CANCELED) { Timer timer = m_timer; if(timer != null) timer.Dispose(); //record the threadID being used for running the callbacks. ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId; //If the kernel event is null at this point, it will be set during lazy construction. if (m_kernelEvent != null) m_kernelEvent.Set(); // update the MRE value. ExecuteCallbackHandlers(throwOnFirstException); Contract.Assert(IsCancellationCompleted, "Expected cancellation to have finished"); } } /// Invoke the Canceled event. The handlers are invoked synchronously in LIFO order. private void ExecuteCallbackHandlers(bool throwOnFirstException) { Contract.Assert(IsCancellationRequested, "