Skip to content

Commit c125fc1

Browse files
authored
Merge pull request #1477 from microsoft/dev/lifengl/allowNoMainThreadCheck
Allow library code to detect the JoinableTaskContext is not associated with Main thread
2 parents a35497f + 9bb119c commit c125fc1

File tree

6 files changed

+38
-0
lines changed

6 files changed

+38
-0
lines changed

src/Microsoft.VisualStudio.Threading/JoinableTaskContext.cs

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

248+
/// <summary>
249+
/// Gets a value indicating whether this instance is not associated with any main thread
250+
/// (e.g. created with <see cref="CreateNoOpContext" />).
251+
/// </summary>
252+
/// <remarks>
253+
/// This allows library code to skip some additional work in the environments that do not have a main thread.
254+
/// </remarks>
255+
public bool IsNoOpContext => this.UnderlyingSynchronizationContext is null;
256+
248257
/// <summary>
249258
/// Gets a value indicating whether the main thread is blocked by any joinable task.
250259
/// </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)