private bool TryDequeueSelfOrDependencies()

in src/Microsoft.VisualStudio.Threading/JoinableTask.cs [1096:1175]


        private bool TryDequeueSelfOrDependencies(bool onMainThread, ref HashSet<IJoinableTaskDependent>? visited, [NotNullWhen(true)] out SingleExecuteProtector? work, out Task? tryAgainAfter)
        {
            using (this.JoinableTaskContext.NoMessagePumpSynchronizationContext.Apply())
            {
                lock (this.JoinableTaskContext.SyncContextLock)
                {
                    if (this.IsFullyCompleted)
                    {
                        work = null;
                        tryAgainAfter = null;
                        return false;
                    }

                    if (this.pendingEventCount > 0)
                    {
                        this.pendingEventCount--;

                        if (this.pendingEventSource is object)
                        {
                            if (this.pendingEventSource.TryGetTarget(out JoinableTask? pendingSource) &&
                                (pendingSource == this ||
                                 (!this.HasPotentialUnreachableDependents && JoinableTaskDependencyGraph.IsDependingSynchronousTask(pendingSource, this))))
                            {
                                ExecutionQueue? queue = onMainThread ? pendingSource.mainThreadQueue : pendingSource.threadPoolQueue;
                                if (queue is object && !queue.IsCompleted && queue.TryDequeue(out work))
                                {
                                    if (queue.Count == 0)
                                    {
                                        this.pendingEventSource = null;
                                    }

                                    tryAgainAfter = null;
                                    return true;
                                }
                            }

                            this.pendingEventSource = null;
                        }

                        if (visited is null)
                        {
                            visited = new HashSet<IJoinableTaskDependent>();
                        }
                        else
                        {
                            visited.Clear();
                        }

                        bool foundWork = TryDequeueSelfOrDependencies(this, onMainThread, visited, out work);

                        HashSet<IJoinableTaskDependent>? visitedNodes = visited;
                        if (this.HasPotentialUnreachableDependents)
                        {
                            // We walked the dependencies tree and use this information to update the PotentialUnreachableDependents list.
                            this.PotentialUnreachableDependents!.RemoveWhere(n => visitedNodes.Contains(n));

                            if (!foundWork && this.PotentialUnreachableDependents.Count > 0)
                            {
                                JoinableTaskDependencyGraph.RemoveUnreachableDependentItems(this, this.PotentialUnreachableDependents, visitedNodes);
                                this.PotentialUnreachableDependents.Clear();
                            }
                        }

                        if (foundWork)
                        {
                            Assumes.NotNull(work);

                            tryAgainAfter = null;
                            return true;
                        }
                    }

                    this.pendingEventCount = 0;

                    work = null;
                    tryAgainAfter = this.IsCompleteRequested ? null : this.QueueNeedProcessEvent;
                    return false;
                }
            }
        }