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);
         }
     }
 }
コード例 #3
0
        /// <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);
        }