in src/Microsoft.VisualStudio.Threading/JoinableTaskDependencyGraph.cs [807:881]
private static JoinableTask? AddDependingSynchronousTask(IJoinableTaskDependent taskOrCollection, JoinableTask synchronousTask, ref int totalEventsPending)
{
Requires.NotNull(taskOrCollection, nameof(taskOrCollection));
Requires.NotNull(synchronousTask, nameof(synchronousTask));
Assumes.True(Monitor.IsEntered(taskOrCollection.JoinableTaskContext.SyncContextLock));
JoinableTask? thisJoinableTask = taskOrCollection as JoinableTask;
if (thisJoinableTask is object)
{
if (thisJoinableTask.IsCompleteRequested)
{
if (!thisJoinableTask.IsFullyCompleted)
{
// A completed task might still have pending items in the queue.
int pendingCount = thisJoinableTask.GetPendingEventCountForSynchronousTask(synchronousTask);
if (pendingCount > 0)
{
totalEventsPending += pendingCount;
return thisJoinableTask;
}
}
return null;
}
}
ref JoinableTaskDependentData data = ref taskOrCollection.GetJoinableTaskDependentData();
DependentSynchronousTask? existingTaskTracking = data.dependingSynchronousTaskTracking;
while (existingTaskTracking is object)
{
if (existingTaskTracking.SynchronousTask == synchronousTask)
{
existingTaskTracking.ReferenceCount++;
return null;
}
existingTaskTracking = existingTaskTracking.Next;
}
JoinableTask? eventTriggeringTask = null;
if (thisJoinableTask is object)
{
int pendingItemCount = thisJoinableTask.GetPendingEventCountForSynchronousTask(synchronousTask);
if (pendingItemCount > 0)
{
totalEventsPending += pendingItemCount;
eventTriggeringTask = thisJoinableTask;
}
}
// For a new synchronous task, we need apply it to our child tasks.
var newTaskTracking = new DependentSynchronousTask(synchronousTask)
{
Next = data.dependingSynchronousTaskTracking,
};
Thread.MemoryBarrier();
data.dependingSynchronousTaskTracking = newTaskTracking;
if (data.childDependentNodes is object)
{
foreach (KeyValuePair<IJoinableTaskDependent, int> item in data.childDependentNodes)
{
JoinableTask? childTiggeringTask = AddDependingSynchronousTask(item.Key, synchronousTask, ref totalEventsPending);
if (eventTriggeringTask is null)
{
eventTriggeringTask = childTiggeringTask;
}
}
}
return eventTriggeringTask;
}