Skip to content

Commit dd84240

Browse files
committed
Allow library code to detect the JoinableContext is not associated with main thread
It allows library code to skip certain work under such conditions. For example to build an extensive dependency graph for dataflow dependencies, or dependencies in work queues.
1 parent a35497f commit dd84240

File tree

6 files changed

+35
-0
lines changed

6 files changed

+35
-0
lines changed

src/Microsoft.VisualStudio.Threading/JoinableTaskContext.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ public bool IsWithinJoinableTask
245245
get { return this.AmbientTask is object; }
246246
}
247247

248+
/// <summary>
249+
/// Gets a value indicating whether gets a value indicating the JoinableTask is not associated with any main thread.
250+
/// This allows library code to skip some additional work in the environments that do not have a main thread.
251+
/// </summary>
252+
public bool IsNoOpContext => this.UnderlyingSynchronizationContext is null;
253+
248254
/// <summary>
249255
/// Gets a value indicating whether the main thread is blocked by any joinable task.
250256
/// </summary>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Microsoft.VisualStudio.Threading.AsyncBarrier.SignalAndWait(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask
22
Microsoft.VisualStudio.Threading.IPendingExecutionRequestState
33
Microsoft.VisualStudio.Threading.IPendingExecutionRequestState.IsCompleted.get -> bool
4+
Microsoft.VisualStudio.Threading.JoinableTaskContext.IsNoOpContext.get -> bool
45
static Microsoft.VisualStudio.Threading.JoinableTaskContext.CreateNoOpContext() -> Microsoft.VisualStudio.Threading.JoinableTaskContext!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Microsoft.VisualStudio.Threading.AsyncBarrier.SignalAndWait(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask
22
Microsoft.VisualStudio.Threading.IPendingExecutionRequestState
33
Microsoft.VisualStudio.Threading.IPendingExecutionRequestState.IsCompleted.get -> bool
4+
Microsoft.VisualStudio.Threading.JoinableTaskContext.IsNoOpContext.get -> bool
45
static Microsoft.VisualStudio.Threading.JoinableTaskContext.CreateNoOpContext() -> Microsoft.VisualStudio.Threading.JoinableTaskContext!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Microsoft.VisualStudio.Threading.AsyncBarrier.SignalAndWait(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask
22
Microsoft.VisualStudio.Threading.IPendingExecutionRequestState
33
Microsoft.VisualStudio.Threading.IPendingExecutionRequestState.IsCompleted.get -> bool
4+
Microsoft.VisualStudio.Threading.JoinableTaskContext.IsNoOpContext.get -> bool
45
static Microsoft.VisualStudio.Threading.JoinableTaskContext.CreateNoOpContext() -> Microsoft.VisualStudio.Threading.JoinableTaskContext!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Microsoft.VisualStudio.Threading.AsyncBarrier.SignalAndWait(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask
22
Microsoft.VisualStudio.Threading.IPendingExecutionRequestState
33
Microsoft.VisualStudio.Threading.IPendingExecutionRequestState.IsCompleted.get -> bool
4+
Microsoft.VisualStudio.Threading.JoinableTaskContext.IsNoOpContext.get -> bool
45
static Microsoft.VisualStudio.Threading.JoinableTaskContext.CreateNoOpContext() -> Microsoft.VisualStudio.Threading.JoinableTaskContext!

test/Microsoft.VisualStudio.Threading.Tests/JoinableTaskContextTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ public void Ctor_ExplicitNullSyncContext()
727727
Thread mainThread = Thread.CurrentThread;
728728
Assumes.NotNull(SynchronizationContext.Current);
729729
JoinableTaskContext jtc = JoinableTaskContext.CreateNoOpContext();
730+
Assert.True(jtc.IsNoOpContext);
730731
await TaskScheduler.Default.SwitchTo(alwaysYield: true); // Get off the main thread.
731732
Assert.NotSame(mainThread, Thread.CurrentThread);
732733

@@ -745,6 +746,7 @@ public void Ctor_NullSyncContextArg_AmbientSyncContext()
745746
Thread mainThread = Thread.CurrentThread;
746747
Assumes.NotNull(SynchronizationContext.Current);
747748
JoinableTaskContext jtc = new(null, null);
749+
Assert.False(jtc.IsNoOpContext);
748750
await TaskScheduler.Default.SwitchTo(alwaysYield: true); // Get off the main thread.
749751
Assert.NotSame(mainThread, Thread.CurrentThread);
750752

@@ -762,6 +764,7 @@ public void Ctor_Default()
762764
Thread mainThread = Thread.CurrentThread;
763765
Assumes.NotNull(SynchronizationContext.Current);
764766
JoinableTaskContext jtc = new();
767+
Assert.False(jtc.IsNoOpContext);
765768
await TaskScheduler.Default.SwitchTo(alwaysYield: true); // Get off the main thread.
766769
Assert.NotSame(mainThread, Thread.CurrentThread);
767770

@@ -771,6 +774,28 @@ public void Ctor_Default()
771774
});
772775
}
773776

777+
[Fact]
778+
public void Ctor_DefaultWithNoSyncContext()
779+
{
780+
this.SimulateUIThread(async delegate
781+
{
782+
await TaskScheduler.Default.SwitchTo(alwaysYield: true); // Get off the main thread.
783+
784+
Thread currentThread = Thread.CurrentThread;
785+
786+
Assumes.Null(SynchronizationContext.Current);
787+
JoinableTaskContext jtc = new();
788+
Assert.True(jtc.IsNoOpContext);
789+
790+
await TaskScheduler.Default.SwitchTo();
791+
Assert.Same(currentThread, Thread.CurrentThread);
792+
793+
// Verify that switching to the main thread works.
794+
await jtc.Factory.SwitchToMainThreadAsync(this.TimeoutToken);
795+
Assert.Same(currentThread, Thread.CurrentThread);
796+
});
797+
}
798+
774799
protected override JoinableTaskContext CreateJoinableTaskContext()
775800
{
776801
return new JoinableTaskContextDerived();

0 commit comments

Comments
 (0)