public CancellationTokenSource(int millisecondsDelay) : this() { if (millisecondsDelay < -1) { throw new ArgumentOutOfRangeException("millisecondsDelay"); } if (millisecondsDelay != Timeout.Infinite) { _timeout = new global::Theraot.Core.Theraot.Threading.Timeout <CancellationTokenSource>(_timerCallback, millisecondsDelay, this); } }
public void CancelAfter(int millisecondsDelay) { if (millisecondsDelay < -1) { throw new ArgumentOutOfRangeException("millisecondsDelay"); } CheckDisposed(); if (Thread.VolatileRead(ref _cancelRequested) == 0 && millisecondsDelay != Timeout.Infinite) { if (_timeout == null) { // Have to be careful not to create secondary background timer var newTimer = new global::Theraot.Core.Theraot.Threading.Timeout <CancellationTokenSource>(_timerCallback, Timeout.Infinite, this); var oldTimer = Interlocked.CompareExchange(ref _timeout, newTimer, null); if (!ReferenceEquals(oldTimer, null)) { newTimer.Cancel(); } _timeout.Change(millisecondsDelay); } } }
/// <summary> /// Creates a Task that will complete after a time delay. /// </summary> /// <param name="millisecondsDelay">The number of milliseconds to wait before completing the returned Task</param> /// <param name="cancellationToken">The cancellation token that will be checked prior to completing the returned Task</param> /// <returns>A Task that represents the time delay</returns> /// <exception cref="T:System.ArgumentOutOfRangeException"> /// The <paramref name="millisecondsDelay"/> is less than -1. /// </exception> /// <exception cref="T:System.ObjectDisposedException"> /// The provided <paramref name="cancellationToken"/> has already been disposed. /// </exception> /// <remarks> /// If the cancellation token is signaled before the specified time delay, then the Task is completed in /// Canceled state. Otherwise, the Task is completed in RanToCompletion state once the specified time /// delay has expired. /// </remarks> public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken) { // Throw on non-sensical time if (millisecondsDelay < -1) { throw new ArgumentOutOfRangeException("millisecondsDelay", "The value needs to be either -1 (signifying an infinite timeout), 0 or a positive integer."); } Contract.EndContractBlock(); // some short-cuts in case quick completion is in order if (cancellationToken.IsCancellationRequested) { // return a Task created as already-Canceled return(FromCancellation(cancellationToken)); } if (millisecondsDelay == 0) { // return a Task created as already-RanToCompletion return(CompletedTask); } var source = new TaskCompletionSource <bool>(); if (millisecondsDelay > 0) { var timeout = new global::Theraot.Core.Theraot.Threading.Timeout ( () => { try { source.SetResult(true); } catch (InvalidOperationException exception) { // Already cancelled GC.KeepAlive(exception); } }, millisecondsDelay, cancellationToken ); source.Task.SetPromiseCheck(() => timeout.CheckRemaining()); } if (cancellationToken.CanBeCanceled) { cancellationToken.Register ( () => { try { source.SetCanceled(); } catch (InvalidOperationException exception) { // Already timeout GC.KeepAlive(exception); } } ); } return(source.Task); }