Пример #1
0
        public Task <bool> WaitAsync(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            CheckDisposed();
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout));
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskEx.FromCanceled <bool>(cancellationToken));
            }

            var source = new TaskCompletionSource <bool>();

            if (_canEnter.Wait(0, cancellationToken) && TryOffset(-1, out var dummy))
            {
                source.SetResult(true);
                return(source.Task);
            }

            RootedTimeout.Launch
            (
                () =>
            {
                try
                {
                    source.SetResult(false);
                }
                catch (InvalidCastException exception)
                {
                    // Already canceled
                    No.Op(exception);
                }
            },
                millisecondsTimeout,
                cancellationToken
            );
            cancellationToken.Register
            (
                () =>
            {
                try
                {
                    source.SetCanceled();
                }
                catch (InvalidOperationException exception)
                {
                    // Already timeout
                    No.Op(exception);
                }
            }
            );
            AddWaiter(source);
            return(source.Task);
        }
Пример #2
0
        public Task <bool> WaitAsync(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            var state = GetState();

            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout));
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskExEx.FromCanceled <bool>(cancellationToken));
            }

            var source = new TaskCompletionSource <bool>();

            if (state.CanEnter.Wait(0, cancellationToken) && TryOffset(-1, out var dummy, state))
            {
                source.SetResult(true);
                return(source.Task);
            }

            RootedTimeout.Launch
            (
                () =>
            {
                try
                {
                    source.SetResult(false);
                }
                catch (InvalidCastException exception)
                {
                    // Already canceled
                    _ = exception;
                }
            },
                () =>
            {
                try
                {
                    source.SetCanceled(cancellationToken);
                }
                catch (InvalidOperationException exception)
                {
                    // Already timeout
                    _ = exception;
                }
            },
                millisecondsTimeout,
                cancellationToken
            );
            state.AsyncWaiters.Add(source);
            return(source.Task);
        }
 public CancellationTokenSource(int millisecondsDelay)
     : this()
 {
     if (millisecondsDelay < -1)
     {
         throw new ArgumentOutOfRangeException(nameof(millisecondsDelay));
     }
     if (millisecondsDelay != Timeout.Infinite)
     {
         _timeout = RootedTimeout.Launch(Callback, millisecondsDelay);
     }
 }
Пример #4
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="ArgumentOutOfRangeException">
        ///     The <paramref name="millisecondsDelay" /> is less than -1.
        /// </exception>
        /// <exception cref="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(nameof(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(TaskExEx.FromCanceled(cancellationToken));
            }

            if (millisecondsDelay == 0)
            {
                // return a Task created as already-RanToCompletion
                return(TaskExEx.CompletedTask);
            }

            var source = new TaskCompletionSource <bool>();

            if (cancellationToken.CanBeCanceled)
            {
                source.Task.AssignCancellationToken(cancellationToken, null, null);
            }

            var timeout = RootedTimeout.Launch
                          (
                () => source.TrySetResult(true),
                () => source.TrySetCanceled(),
                millisecondsDelay,
                cancellationToken
                          );

            source.Task.SetPromiseCheck(() => timeout.CheckRemaining());

            return(source.Task);
        }
 public void CancelAfter(int millisecondsDelay)
 {
     if (millisecondsDelay < -1)
     {
         throw new ArgumentOutOfRangeException(nameof(millisecondsDelay));
     }
     CheckDisposed();
     if (Volatile.Read(ref _cancelRequested) == 0 && millisecondsDelay != Timeout.Infinite)
     {
         if (_timeout == null)
         {
             // Have to be careful not to create secondary background timer
             var newTimer = RootedTimeout.Launch(Callback, Timeout.Infinite);
             var oldTimer = Interlocked.CompareExchange(ref _timeout, newTimer, null);
             if (oldTimer != null)
             {
                 newTimer.Cancel();
             }
             _timeout.Change(millisecondsDelay);
         }
     }
 }
Пример #6
0
 public static void CancelAfter(this CancellationTokenSource cancellationTokenSource, TimeSpan delay)
 {
     if (cancellationTokenSource == null)
     {
         throw new NullReferenceException();
     }
     GC.KeepAlive(cancellationTokenSource.Token);
     RootedTimeout.Launch
     (
         () =>
     {
         try
         {
             cancellationTokenSource.Cancel();
         }
         catch (ObjectDisposedException exception)
         {
             No.Op(exception);
         }
     },
         delay
     );
 }
Пример #7
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(nameof(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 = RootedTimeout.Launch
                              (
                    () =>
                {
                    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);
        }
Пример #8
0
 public static void CancelAfter(this CancellationTokenSource cancellationToken, TimeSpan delay)
 {
     RootedTimeout.Launch(cancellationToken.Cancel, delay);
 }
Пример #9
0
 public static void CancelAfter(this CancellationTokenSource cancellationToken, int millisecondsDelay)
 {
     RootedTimeout.Launch(cancellationToken.Cancel, millisecondsDelay);
 }