Exemplo n.º 1
0
        /// <summary>Performs the asynchronous wait.</summary>
        /// <param name="asyncWaiter">The asynchronous waiter.</param>
        /// <param name="millisecondsTimeout">The timeout.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The task to return to the caller.</returns>
        private async Task <bool> WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int millisecondsTimeout, CancellationToken cancellationToken)
        {
            Debug.Assert(asyncWaiter != null, "Waiter should have been constructed");
            Debug.Assert(Monitor.IsEntered(m_lockObjAndDisposed), "Requires the lock be held");

            await new ConfiguredNoThrowAwaiter <bool>(asyncWaiter.WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout), cancellationToken));

            if (cancellationToken.IsCancellationRequested)
            {
                // If we might be running as part of a cancellation callback, force the completion to be asynchronous
                // so as to maintain semantics similar to when no token is passed (neither Release nor Cancel would invoke
                // continuations off of this task).
                await TaskScheduler.Default;
            }

            if (asyncWaiter.IsCompleted)
            {
                return(true); // successfully acquired
            }

            // The wait has timed out or been canceled.

            // If the await completed synchronously, we still hold the lock.  If it didn't,
            // we no longer hold the lock.  As such, acquire it.
            lock (m_lockObjAndDisposed)
            {
                // Remove the task from the list.  If we're successful in doing so,
                // we know that no one else has tried to complete this waiter yet,
                // so we can safely cancel or timeout.
                if (RemoveAsyncWaiter(asyncWaiter))
                {
                    cancellationToken.ThrowIfCancellationRequested(); // cancellation occurred
                    return(false);                                    // timeout occurred
                }
            }

            // The waiter had already been removed, which means it's already completed or is about to
            // complete, so let it, and don't return until it does.
            return(await asyncWaiter.ConfigureAwait(false));
        }