@@ -6,6 +6,7 @@ namespace Microsoft.VisualStudio.Threading
66 using System ;
77 using System . Collections . Generic ;
88 using System . Diagnostics ;
9+ using System . Diagnostics . CodeAnalysis ;
910 using System . Linq ;
1011 using System . Threading ;
1112
@@ -47,7 +48,7 @@ internal static bool HasMainThreadSynchronousTaskWaiting(IJoinableTaskDependent
4748 {
4849 lock ( taskItem . JoinableTaskContext . SyncContextLock )
4950 {
50- return taskItem . GetJoinableTaskDependentData ( ) . HasMainThreadSynchronousTaskWaiting ( ) ;
51+ return taskItem . GetJoinableTaskDependentData ( ) . HasMainThreadSynchronousTaskWaiting ( taskItem ) ;
5152 }
5253 }
5354 }
@@ -223,7 +224,8 @@ internal static HashSet<JoinableTask> GetDependentTasksFromCandidates(IEnumerabl
223224 /// Computes dependency graph to clean up all potential unreachable dependents items.
224225 /// </summary>
225226 /// <param name="syncTask">A thread blocking sychornizing task.</param>
226- internal static void CleanUpPotentialUnreachableDependentItems ( JoinableTask syncTask )
227+ /// <returns>True if it removes any unreachable items.</returns>
228+ internal static bool CleanUpPotentialUnreachableDependentItems ( JoinableTask syncTask , [ MaybeNullWhen ( false ) ] out HashSet < IJoinableTaskDependent > ? allReachableNodes )
227229 {
228230 Requires . NotNull ( syncTask , nameof ( syncTask ) ) ;
229231
@@ -240,9 +242,23 @@ internal static void CleanUpPotentialUnreachableDependentItems(JoinableTask sync
240242
241243 JoinableTaskDependentData . ComputeSelfAndDescendentOrJoinedJobsAndRemainTasks ( syncTaskItem , reachableNodes , unreachableItems ) ;
242244
245+ syncTask . PotentialUnreachableDependents = null ;
246+ allReachableNodes = reachableNodes ;
247+
243248 // force to remove all invalid items
244- JoinableTaskDependentData . RemoveUnreachableDependentItems ( syncTask , unreachableItems , reachableNodes ) ;
249+ if ( unreachableItems . Count > 0 )
250+ {
251+ JoinableTaskDependentData . RemoveUnreachableDependentItems ( syncTask , unreachableItems , reachableNodes ) ;
252+
253+ return true ;
254+ }
255+ }
256+ else
257+ {
258+ allReachableNodes = null ;
245259 }
260+
261+ return false ;
246262 }
247263
248264 /// <summary>
@@ -564,10 +580,8 @@ internal bool HasDirectDependency(IJoinableTaskDependent dependency)
564580 /// Gets a value indicating whether the main thread is waiting for the task's completion
565581 /// This method is expected to be used with the JTF lock.
566582 /// </summary>
567- internal bool HasMainThreadSynchronousTaskWaiting ( )
583+ internal bool HasMainThreadSynchronousTaskWaiting ( IJoinableTaskDependent taskItem )
568584 {
569- var hasDoneCleanUp = false ;
570-
571585 DependentSynchronousTask ? existingTaskTracking = this . dependingSynchronousTaskTracking ;
572586 while ( existingTaskTracking is object )
573587 {
@@ -577,10 +591,12 @@ internal bool HasMainThreadSynchronousTaskWaiting()
577591 if ( existingTaskTracking . SynchronousTask . PotentialUnreachableDependents != null )
578592 {
579593 // This might remove the current tracking item from the linked list, so we capture next node first.
580- CleanUpPotentialUnreachableDependentItems ( existingTaskTracking . SynchronousTask ) ;
581-
582- // We need check it again after the cleanup work has finished.
583- hasDoneCleanUp = true ;
594+ if ( ! CleanUpPotentialUnreachableDependentItems ( existingTaskTracking . SynchronousTask , out HashSet < IJoinableTaskDependent > ? allReachableNodes ) ||
595+ allReachableNodes ! . Contains ( taskItem ) )
596+ {
597+ // this task is still a dependenting task
598+ return true ;
599+ }
584600 }
585601 else
586602 {
@@ -591,20 +607,6 @@ internal bool HasMainThreadSynchronousTaskWaiting()
591607 existingTaskTracking = nextTrackingTask ;
592608 }
593609
594- if ( hasDoneCleanUp )
595- {
596- existingTaskTracking = this . dependingSynchronousTaskTracking ;
597- while ( existingTaskTracking is object )
598- {
599- if ( ( existingTaskTracking . SynchronousTask . State & JoinableTask . JoinableTaskFlags . SynchronouslyBlockingMainThread ) == JoinableTask . JoinableTaskFlags . SynchronouslyBlockingMainThread )
600- {
601- return true ;
602- }
603-
604- existingTaskTracking = existingTaskTracking . Next ;
605- }
606- }
607-
608610 return false ;
609611 }
610612
0 commit comments