public async Task TaskFirst(ValueTaskSourceStatus status, bool async)
        {
            using var source = LazyTaskCompletionSource.Create();
            Assert.False(source.HasTask);
            Assert.False(source.HasSource);
            var task = source.Task;

            Assert.True(source.HasTask);
            Assert.True(source.HasSource);
            switch (status)
            {
            case ValueTaskSourceStatus.Canceled:
                Assert.True(source.TrySetCanceled());
                Assert.False(source.TrySetCanceled());
                try
                {
                    if (async)
                    {
                        await task;
                    }
                    else
                    {
                        task.GetAwaiter().GetResult();
                    }
                }
                catch (OperationCanceledException) { }
                break;

            case ValueTaskSourceStatus.Faulted:
                Assert.True(source.TrySetException(new TestException()));
                Assert.False(source.TrySetException(new TestException()));
                try
                {
                    if (async)
                    {
                        await task;
                    }
                    else
                    {
                        task.GetAwaiter().GetResult();
                    }
                }
                catch (TestException) { }
                break;

            case ValueTaskSourceStatus.Succeeded:
                Assert.True(source.TrySetResult());
                Assert.False(source.TrySetResult());
                if (async)
                {
                    await task;
                }
                else
                {
                    task.Wait();
                }
                Assert.NotSame(task, TaskUtils.CompletedTask);
                break;
            }
        }
Beispiel #2
0
            public void Success()
            {
                status = ValueTaskSourceStatus.Succeeded;
                var previousContinuation = Interlocked.CompareExchange(ref this.continuation, CallbackCompleted, null);

                if (previousContinuation != null)
                {
                    // Async work completed, continue with... continuation
                    ExecutionContext ec = executionContext;
                    if (ec == null)
                    {
                        InvokeContinuation(previousContinuation, this.state, forceAsync: false);
                    }
                    else
                    {
                        // This case should be relatively rare, as the async Task/ValueTask method builders
                        // use the awaiter's UnsafeOnCompleted, so this will only happen with code that
                        // explicitly uses the awaiter's OnCompleted instead.
                        executionContext = null;
                        ExecutionContext.Run(ec, runState =>
                        {
                            var t = (Tuple <_source, Action <object>, object>)runState;
                            t.Item1.InvokeContinuation(t.Item2, t.Item3, forceAsync: false);
                        }, Tuple.Create(this, previousContinuation, this.state));
                    }
                }
            }
Beispiel #3
0
        /// <summary>Creates a <see cref="Task{TResult}"/> to represent the <see cref="IValueTaskSource{TResult}"/>.</summary>
        /// <remarks>
        /// The <see cref="IValueTaskSource{TResult}"/> is passed in rather than reading and casting <see cref="_obj"/>
        /// so that the caller can pass in an object it's already validated.
        /// </remarks>
        private Task <TResult> GetTaskForValueTaskSource(IValueTaskSource <TResult> t)
        {
            ValueTaskSourceStatus status = t.GetStatus(_token);

            if (status != ValueTaskSourceStatus.Pending)
            {
                try
                {
                    // Get the result of the operation and return a task for it.
                    // If any exception occurred, propagate it
                    return(AsyncTaskMethodBuilder <TResult> .GetTaskForResult(t.GetResult(_token)));

                    // If status is Faulted or Canceled, GetResult should throw.  But
                    // we can't guarantee every implementation will do the "right thing".
                    // If it doesn't throw, we just treat that as success and ignore
                    // the status.
                }
                catch (Exception exc)
                {
                    if (status == ValueTaskSourceStatus.Canceled)
                    {
                        if (exc is OperationCanceledException oce)
                        {
                            var task = new Task <TResult>();
                            task.TrySetCanceled(oce.CancellationToken, oce);
                            return(task);
                        }

                        Task <TResult> canceledTask = s_canceledTask;
                        if (canceledTask == null)
                        {
                            // Benign race condition to initialize cached task, as identity doesn't matter.
                            s_canceledTask = Task.FromCanceled <TResult>(new CancellationToken(true));
                        }
                        return(canceledTask);
                    }
                    else
                    {
                        return(Task.FromException <TResult>(exc));
                    }
                }
            }

            return(new ValueTaskSourceAsTask(t, _token));
        }
Beispiel #4
0
        /// <summary>Creates a <see cref="Task"/> to represent the <see cref="IValueTaskSource"/>.</summary>
        /// <remarks>
        /// The <see cref="IValueTaskSource"/> is passed in rather than reading and casting <see cref="_obj"/>
        /// so that the caller can pass in an object it's already validated.
        /// </remarks>
        private Task GetTaskForValueTaskSource(IValueTaskSource t)
        {
            ValueTaskSourceStatus status = t.GetStatus(_token);

            if (status != ValueTaskSourceStatus.Pending)
            {
                try
                {
                    // Propagate any exceptions that may have occurred, then return
                    // an already successfully completed task.
                    t.GetResult(_token);
                    return(Task.CompletedTask);

                    // If status is Faulted or Canceled, GetResult should throw.  But
                    // we can't guarantee every implementation will do the "right thing".
                    // If it doesn't throw, we just treat that as success and ignore
                    // the status.
                }
                catch (Exception exc)
                {
                    if (status == ValueTaskSourceStatus.Canceled)
                    {
                        if (exc is OperationCanceledException oce)
                        {
                            var task = new Task();
                            task.TrySetCanceled(oce.CancellationToken, oce);
                            return(task);
                        }

                        // Benign race condition to initialize cached task, as identity doesn't matter.
                        return(s_canceledTask ??= Task.FromCanceled(new CancellationToken(canceled: true)));
                    }
                    else
                    {
                        return(Task.FromException(exc));
                    }
                }
            }

            return(new ValueTaskSourceAsTask(t, _token));
        }
Beispiel #5
0
        private Task GetTaskForValueTaskSource(IValueTaskSource t)
        {
            ValueTaskSourceStatus status = t.GetStatus(_token);

            if (status == ValueTaskSourceStatus.Pending)
            {
                return(new ValueTaskSourceAsTask(t, _token).Task);
            }
            try
            {
                t.GetResult(_token);
                return(CompletedTask);
            }
            catch (Exception ex)
            {
                if (status == ValueTaskSourceStatus.Canceled)
                {
                    return(s_canceledTask);
                }
                TaskCompletionSource <Boolean> completionSource = new TaskCompletionSource <Boolean>();
                completionSource.TrySetException(ex);
                return(completionSource.Task);
            }
        }
Beispiel #6
0
 public void Cancel()
 {
     status = ValueTaskSourceStatus.Canceled;
 }