internal CancellableJoinComputation()

in src/Microsoft.VisualStudio.Threading/CancellableJoinComputation.cs [55:133]


        internal CancellableJoinComputation(Func<CancellationToken, Task> taskFactory, bool allowCancelled)
        {
            Requires.NotNull(taskFactory, nameof(taskFactory));

            if (allowCancelled)
            {
                this.isCancellationAllowed = true;
                this.combinedCancellationTokenSource = new CancellationTokenSource();
                this.joinedWaitingList = new List<WaitingCancellationStatus>(capacity: 2);
            }

            this.InnerTask = taskFactory(this.combinedCancellationTokenSource?.Token ?? CancellationToken.None);

            if (allowCancelled)
            {
                // Note: this continuation is chained asynchronously to prevent being inlined when we trigger the combined cancellation token.
                this.InnerTask.ContinueWith(
                    (t, s) =>
                    {
                        var me = (CancellableJoinComputation)s!;

                        List<WaitingCancellationStatus> allWaitingTasks;
                        CancellationTokenSource? combinedCancellationTokenSource;
                        lock (me.syncObject)
                        {
                            Assumes.NotNull(me.joinedWaitingList);

                            allWaitingTasks = me.joinedWaitingList;
                            combinedCancellationTokenSource = me.combinedCancellationTokenSource;

                            me.joinedWaitingList = null;
                            me.combinedCancellationTokenSource = null;
                        }

                        combinedCancellationTokenSource?.Dispose();

                        if (t.IsCanceled)
                        {
                            for (int i = 0; i < allWaitingTasks.Count; i++)
                            {
                                WaitingCancellationStatus status = allWaitingTasks[i];
                                if (status.CancellationToken.IsCancellationRequested)
                                {
                                    status.TrySetCanceled(status.CancellationToken);
                                }
                                else
                                {
                                    status.TrySetCanceled();
                                }

                                status.Dispose();
                            }
                        }
                        else if (t.IsFaulted)
                        {
                            System.Collections.ObjectModel.ReadOnlyCollection<Exception> exceptions = t.Exception!.InnerExceptions;
                            for (int i = 0; i < allWaitingTasks.Count; i++)
                            {
                                WaitingCancellationStatus status = allWaitingTasks[i];
                                status.TrySetException(exceptions);
                                status.Dispose();
                            }
                        }
                        else
                        {
                            for (int i = 0; i < allWaitingTasks.Count; i++)
                            {
                                WaitingCancellationStatus status = allWaitingTasks[i];
                                status.TrySetResult(true);
                                status.Dispose();
                            }
                        }
                    },
                    this,
                    CancellationToken.None,
                    TaskContinuationOptions.RunContinuationsAsynchronously,
                    TaskScheduler.Default).Forget();
            }
        }