9 [__DynamicallyInvokable]
10 [HostProtection(
SecurityAction.LinkDemand, Synchronization =
true, ExternalThreading =
true)]
17 private static readonly
int s_nLists = (PlatformHelper.ProcessorCount > 24) ? 24 : PlatformHelper.ProcessorCount;
21 private volatile SparselyPopulatedArray<CancellationCallbackInfo>[] m_registeredCallbacksLists;
23 private const int CANNOT_BE_CANCELED = 0;
25 private const int NOT_CANCELED = 1;
27 private const int NOTIFYING = 2;
29 private const int NOTIFYINGCOMPLETE = 3;
31 private volatile int m_state;
33 private volatile int m_threadIDExecutingCallbacks = -1;
35 private bool m_disposed;
39 private static readonly Action<object> s_LinkedTokenCancelDelegate = LinkedTokenCancelDelegate;
41 private volatile CancellationCallbackInfo m_executingCallback;
43 private volatile Timer m_timer;
45 private static readonly
TimerCallback s_timerCallback = TimerCallbackLogic;
50 [__DynamicallyInvokable]
53 [__DynamicallyInvokable]
60 internal bool IsCancellationCompleted => m_state == 3;
62 internal bool IsDisposed => m_disposed;
64 internal int ThreadIDExecutingCallbacks
68 return m_threadIDExecutingCallbacks;
72 m_threadIDExecutingCallbacks = value;
79 [__DynamicallyInvokable]
80 public CancellationToken Token
82 [__DynamicallyInvokable]
90 internal bool CanBeCanceled => m_state != 0;
97 if (m_kernelEvent !=
null)
101 ManualResetEvent manualResetEvent =
new ManualResetEvent(initialState:
false);
102 if (Interlocked.CompareExchange(ref m_kernelEvent, manualResetEvent,
null) !=
null)
106 if (IsCancellationRequested)
110 return m_kernelEvent;
114 internal CancellationCallbackInfo ExecutingCallback => m_executingCallback;
116 private static void LinkedTokenCancelDelegate(
object source)
118 CancellationTokenSource cancellationTokenSource = source as CancellationTokenSource;
119 cancellationTokenSource.Cancel();
123 [__DynamicallyInvokable]
131 m_state = (
set ? 3 : 0);
140 [__DynamicallyInvokable]
144 if (num < -1 || num >
int.MaxValue)
148 InitializeWithTimer((
int)num);
155 [__DynamicallyInvokable]
158 if (millisecondsDelay < -1)
162 InitializeWithTimer(millisecondsDelay);
165 private void InitializeWithTimer(
int millisecondsDelay)
168 m_timer =
new Timer(s_timerCallback,
this, millisecondsDelay, -1);
174 [__DynamicallyInvokable]
177 Cancel(throwOnFirstException:
false);
185 [__DynamicallyInvokable]
186 public void Cancel(
bool throwOnFirstException)
189 NotifyCancellation(throwOnFirstException);
196 [__DynamicallyInvokable]
200 if (num < -1 || num >
int.MaxValue)
204 CancelAfter((
int)num);
211 [__DynamicallyInvokable]
215 if (millisecondsDelay < -1)
219 if (IsCancellationRequested)
225 Timer timer =
new Timer(s_timerCallback,
this, -1, -1);
233 m_timer.Change(millisecondsDelay, -1);
240 private static void TimerCallbackLogic(
object obj)
243 if (!cancellationTokenSource.IsDisposed)
247 cancellationTokenSource.
Cancel();
251 if (!cancellationTokenSource.IsDisposed)
260 [__DynamicallyInvokable]
263 Dispose(disposing:
true);
270 [__DynamicallyInvokable]
271 protected virtual void Dispose(
bool disposing)
273 if (!disposing || m_disposed)
282 if (linkingRegistrations !=
null)
284 m_linkingRegistrations =
null;
285 for (
int i = 0; i < linkingRegistrations.Length; i++)
287 linkingRegistrations[i].
Dispose();
290 m_registeredCallbacksLists =
null;
291 if (m_kernelEvent !=
null)
293 m_kernelEvent.Close();
294 m_kernelEvent =
null;
299 internal void ThrowIfDisposed()
303 ThrowObjectDisposedException();
307 private static void ThrowObjectDisposedException()
309 throw new ObjectDisposedException(
null, Environment.GetResourceString(
"CancellationTokenSource_Disposed"));
312 internal static CancellationTokenSource InternalGetStaticSource(
bool set)
316 return _staticSource_NotCancelable;
318 return _staticSource_Set;
321 internal CancellationTokenRegistration InternalRegister(Action<object> callback,
object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
323 if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
327 if (!IsCancellationRequested)
329 if (m_disposed && !AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
331 return default(CancellationTokenRegistration);
333 int num = Thread.CurrentThread.ManagedThreadId % s_nLists;
334 CancellationCallbackInfo cancellationCallbackInfo =
new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext,
this);
335 SparselyPopulatedArray<CancellationCallbackInfo>[] array = m_registeredCallbacksLists;
338 SparselyPopulatedArray<CancellationCallbackInfo>[] array2 =
new SparselyPopulatedArray<CancellationCallbackInfo>[s_nLists];
339 array = Interlocked.CompareExchange(ref m_registeredCallbacksLists, array2,
null);
345 SparselyPopulatedArray<CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read(ref array[num]);
346 if (sparselyPopulatedArray ==
null)
348 SparselyPopulatedArray<CancellationCallbackInfo> value =
new SparselyPopulatedArray<CancellationCallbackInfo>(4);
349 Interlocked.CompareExchange(ref array[num], value,
null);
350 sparselyPopulatedArray = array[num];
352 SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> registrationInfo = sparselyPopulatedArray.Add(cancellationCallbackInfo);
353 CancellationTokenRegistration result =
new CancellationTokenRegistration(cancellationCallbackInfo, registrationInfo);
354 if (!IsCancellationRequested)
358 if (!result.TryDeregister())
363 callback(stateForCallback);
364 return default(CancellationTokenRegistration);
367 private void NotifyCancellation(
bool throwOnFirstException)
369 if (!IsCancellationRequested && Interlocked.CompareExchange(ref m_state, 2, 1) == 1)
372 ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
373 if (m_kernelEvent !=
null)
377 ExecuteCallbackHandlers(throwOnFirstException);
381 private void ExecuteCallbackHandlers(
bool throwOnFirstException)
384 SparselyPopulatedArray<CancellationCallbackInfo>[] registeredCallbacksLists = m_registeredCallbacksLists;
385 if (registeredCallbacksLists ==
null)
387 Interlocked.Exchange(ref m_state, 3);
392 for (
int i = 0; i < registeredCallbacksLists.Length; i++)
394 SparselyPopulatedArray<CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read(ref registeredCallbacksLists[i]);
395 if (sparselyPopulatedArray !=
null)
397 for (SparselyPopulatedArrayFragment<CancellationCallbackInfo> sparselyPopulatedArrayFragment = sparselyPopulatedArray.Tail; sparselyPopulatedArrayFragment !=
null; sparselyPopulatedArrayFragment = sparselyPopulatedArrayFragment.Prev)
399 for (
int num = sparselyPopulatedArrayFragment.Length - 1; num >= 0; num--)
401 m_executingCallback = sparselyPopulatedArrayFragment[num];
402 if (m_executingCallback !=
null)
404 CancellationCallbackCoreWorkArguments cancellationCallbackCoreWorkArguments =
new CancellationCallbackCoreWorkArguments(sparselyPopulatedArrayFragment, num);
407 if (m_executingCallback.TargetSyncContext !=
null)
409 m_executingCallback.TargetSyncContext.Send(CancellationCallbackCoreWork_OnSyncContext, cancellationCallbackCoreWorkArguments);
410 ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
414 CancellationCallbackCoreWork(cancellationCallbackCoreWorkArguments);
417 catch (Exception item)
419 if (throwOnFirstException)
438 m_executingCallback =
null;
439 Thread.MemoryBarrier();
445 throw new AggregateException(list);
448 private void CancellationCallbackCoreWork_OnSyncContext(
object obj)
450 CancellationCallbackCoreWork((CancellationCallbackCoreWorkArguments)obj);
453 private void CancellationCallbackCoreWork(CancellationCallbackCoreWorkArguments args)
455 CancellationCallbackInfo cancellationCallbackInfo = args.m_currArrayFragment.SafeAtomicRemove(args.m_currArrayIndex, m_executingCallback);
456 if (cancellationCallbackInfo == m_executingCallback)
458 if (cancellationCallbackInfo.TargetExecutionContext !=
null)
460 cancellationCallbackInfo.CancellationTokenSource.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
462 cancellationCallbackInfo.ExecuteCallback();
471 [__DynamicallyInvokable]
479 cancellationTokenSource.m_linkingRegistrations[0] = token1.InternalRegisterWithoutEC(s_LinkedTokenCancelDelegate, cancellationTokenSource);
484 if (cancellationTokenSource.m_linkingRegistrations ==
null)
489 cancellationTokenSource.m_linkingRegistrations[num] = token2.InternalRegisterWithoutEC(s_LinkedTokenCancelDelegate, cancellationTokenSource);
491 return cancellationTokenSource;
502 [__DynamicallyInvokable]
509 if (tokens.Length == 0)
515 for (
int i = 0; i < tokens.Length; i++)
517 if (tokens[i].CanBeCanceled)
519 cancellationTokenSource.m_linkingRegistrations[i] = tokens[i].InternalRegisterWithoutEC(s_LinkedTokenCancelDelegate, cancellationTokenSource);
522 return cancellationTokenSource;
525 internal void WaitForCallbackToComplete(CancellationCallbackInfo callbackInfo)
528 while (ExecutingCallback == callbackInfo)
CancellationTokenSource(int millisecondsDelay)
Initializes a new instance of the T:System.Threading.CancellationTokenSource class that will be cance...
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
CancellationTokenSource(TimeSpan delay)
Initializes a new instance of the T:System.Threading.CancellationTokenSource class that will be cance...
Propagates notification that operations should be canceled.
Encapsulates operating system–specific objects that wait for exclusive access to shared resources.
static void SuppressFinalize(object obj)
Requests that the common language runtime not call the finalizer for the specified object.
Provides support for spin-based waiting.
static CancellationTokenSource CreateLinkedTokenSource(CancellationToken token1, CancellationToken token2)
Creates a T:System.Threading.CancellationTokenSource that will be in the canceled state when any of t...
Provides a mechanism for releasing unmanaged resources.To browse the .NET Framework source code for t...
void Cancel()
Communicates a request for cancellation.
The exception that is thrown when the value of an argument is outside the allowable range of values a...
Represents a callback delegate that has been registered with a T:System.Threading....
double TotalMilliseconds
Gets the value of the current T:System.TimeSpan structure expressed in whole and fractional milliseco...
bool CanBeCanceled
Gets whether this token is capable of being in the canceled state.
The exception that is thrown when an operation is performed on a disposed object.
SecurityAction
Specifies the security actions that can be performed using declarative security.
Provides information about, and means to manipulate, the current environment and platform....
static int CompareExchange(ref int location1, int value, int comparand)
Compares two 32-bit signed integers for equality and, if they are equal, replaces the first value.
void Dispose()
Releases all resources used by the current instance of the T:System.Threading.CancellationTokenSource...
delegate void TimerCallback(object state)
Represents the method that handles calls from a T:System.Threading.Timer.
Provides a mechanism for executing a method on a thread pool thread at specified intervals....
Notifies one or more waiting threads that an event has occurred. This class cannot be inherited.
void Cancel(bool throwOnFirstException)
Communicates a request for cancellation, and specifies whether remaining callbacks and cancelable ope...
bool Dispose(WaitHandle notifyObject)
Releases all resources used by the current instance of T:System.Threading.Timer and signals when the ...
Controls the system garbage collector, a service that automatically reclaims unused memory.
CancellationTokenSource()
Initializes a new instance of the T:System.Threading.CancellationTokenSource class.
The exception that is thrown when one of the arguments provided to a method is not valid.
Represents a strongly typed list of objects that can be accessed by index. Provides methods to search...
void SpinOnce()
Performs a single spin.
Represents a time interval.To browse the .NET Framework source code for this type,...
static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens)
Creates a T:System.Threading.CancellationTokenSource that will be in the canceled state when any of t...
Signals to a T:System.Threading.CancellationToken that it should be canceled.
bool IsCancellationRequested
Gets whether cancellation has been requested for this T:System.Threading.CancellationTokenSource.
void CancelAfter(int millisecondsDelay)
Schedules a cancel operation on this T:System.Threading.CancellationTokenSource after the specified n...
Provides atomic operations for variables that are shared by multiple threads.
void Dispose()
Releases all resources used by the current instance of the T:System.Threading.CancellationTokenRegist...
void CancelAfter(TimeSpan delay)
Schedules a cancel operation on this T:System.Threading.CancellationTokenSource after the specified t...
virtual void Dispose(bool disposing)
Releases the unmanaged resources used by the T:System.Threading.CancellationTokenSource class and opt...