Example #1
0
        /// <summary>
        /// Gets a task for the completion source which execute continuations for TaskCompletionSource.SetResult asynchronously.
        /// </summary>
        public static Task <T> GetAsyncCompletion <T>(this TaskSourceSlim <T> completion)
        {
            if (completion.Task.IsCompleted)
            {
                return(completion.Task);
            }

            return(GetTaskWithAsyncContinuation(completion));
        }
Example #2
0
        private static async Task <T> GetTaskWithAsyncContinuation <T>(this TaskSourceSlim <T> completion)
        {
            var result = await completion.Task;

            // Yield to not block the thread which sets the result of the completion
            await Task.Yield();

            return(result);
        }
Example #3
0
        public static Task <T> FromException <T>(Exception ex)
        {
            Contract.RequiresNotNull(ex);

            var failureSource = TaskSourceSlim.Create <T>();

            failureSource.SetException(ex);
            return(failureSource.Task);
        }
Example #4
0
        public static Task <T> FromException <T>(Exception ex)
        {
            Contract.Requires(ex != null);
            Contract.Ensures(Contract.Result <Task <T> >() != null);

            var failureSource = TaskSourceSlim.Create <T>();

            failureSource.SetException(ex);
            return(failureSource.Task);
        }
Example #5
0
        /// <summary>
        /// Gets <see cref="CancellationTokenAwaitable"/> from a given <paramref name="token"/> that can be used in async methods to await the cancellation.
        /// </summary>
        /// <remarks>
        /// The method returns a special disposable type instead of just returning a Task.
        /// This is important, because the client code need to "unregister" the callback from the token when some other operations are done and the cancellation is no longer relevant.
        /// Just returning a task on a token that is never trigerred will effectively cause a memory leak.
        /// Here is a previous implementation of this method:
        /// <code>public static async Task ToAwaitable(this CancellationToken token) { try {await Task.Delay(Timeout.Infinite, token);} catch(TaskCanceledException) {} }</code>
        /// The `Delay` impelmentaiton checks if the timeout is infinite and won't start the timer, but it still will create a `DelayPromise` instance
        /// and will register for the cancellation.
        /// It means that if we call such a method many times with the same cancellation token, the registration list will grow indefinitely causing potential performance issues.
        /// </remarks>
        public static CancellationTokenAwaitable ToAwaitable(this CancellationToken token)
        {
            if (!token.CanBeCanceled)
            {
                // If the token can not be canceled, return a special global instance with a task that will never be finished.
                return(CancellationTokenAwaitable.NonCancellableAwaitable);
            }

            var tcs          = TaskSourceSlim.Create <object>();
            var registration = token.Register(static tcs => ((TaskSourceSlim <object>)tcs).SetResult(null), tcs);
Example #6
0
        /// <summary>
        /// Creates a TPL Task that is marked as completed when any <see cref="WaitHandle"/> in the array is signaled.
        /// </summary>
        /// <param name="handles">The handles whose signals triggers the task to be completed.  Do not use a <see cref="Mutex"/> here.</param>
        /// <param name="timeout">The timeout (in milliseconds) after which the task will return a value of WaitTimeout.</param>
        /// <returns>A Task that is completed after any handle is signaled.</returns>
        /// <remarks>
        /// There is a (brief) time delay between when the handles are signaled and when the task is marked as completed.
        /// </remarks>
        public static Task <int> ToTask(this WaitHandle[] handles, int timeout = Timeout.Infinite)
        {
            Contract.Requires(handles != null);
            Contract.RequiresForAll(handles, handle => handles != null);

            var tcs             = TaskSourceSlim.Create <int>();
            int signalledHandle = WaitHandle.WaitAny(handles, 0);

            if (signalledHandle != WaitHandle.WaitTimeout)
            {
                // An optimization for if the handle is already signaled
                // to return a completed task.
                tcs.SetResult(signalledHandle);
            }
            else
            {
                var localVariableInitLock = new object();
                lock (localVariableInitLock)
                {
                    RegisteredWaitHandle[] callbackHandles = new RegisteredWaitHandle[handles.Length];
                    for (int i = 0; i < handles.Length; i++)
                    {
                        callbackHandles[i] = ThreadPool.RegisterWaitForSingleObject(
                            handles[i],
                            (state, timedOut) =>
                        {
                            int handleIndex = (int)state;
                            if (timedOut)
                            {
                                tcs.TrySetResult(WaitHandle.WaitTimeout);
                            }
                            else
                            {
                                tcs.TrySetResult(handleIndex);
                            }

                            // We take a lock here to make sure the outer method has completed setting the local variable callbackHandles contents.
                            lock (localVariableInitLock)
                            {
                                foreach (var handle in callbackHandles)
                                {
                                    handle.Unregister(null);
                                }
                            }
                        },
                            state: i,
                            millisecondsTimeOutInterval: timeout,
                            executeOnlyOnce: true);
                    }
                }
            }

            return(tcs.Task);
        }
Example #7
0
        static BoolTask()
        {
            TrueCompletion = TaskSourceSlim.Create <bool>();
            TrueCompletion.SetResult(true);
            True = TrueCompletion.Task;

            TrueCompletionSource = new TaskCompletionSource <bool>();
            TrueCompletionSource.SetResult(true);

            FalseCompletion = TaskSourceSlim.Create <bool>();
            FalseCompletion.SetResult(false);
            False = FalseCompletion.Task;

            FalseCompletionSource = new TaskCompletionSource <bool>(false);
            FalseCompletionSource.SetResult(false);
        }