diff --git a/src/Microsoft.VisualStudio.Threading/ReentrantSemaphore.cs b/src/Microsoft.VisualStudio.Threading/ReentrantSemaphore.cs
index 3e7c581a5..792cac1ce 100644
--- a/src/Microsoft.VisualStudio.Threading/ReentrantSemaphore.cs
+++ b/src/Microsoft.VisualStudio.Threading/ReentrantSemaphore.cs
@@ -153,7 +153,8 @@ public static ReentrantSemaphore Create(int initialCount = 1, JoinableTaskContex
///
/// A cancellation token.
/// A task that completes with the result of , after the semaphore has been exited.
- public abstract Task ExecuteAsync(Func operation, CancellationToken cancellationToken = default);
+ public Task ExecuteAsync(Func operation, CancellationToken cancellationToken = default)
+ => this.ExecuteAsync(operation, null, cancellationToken);
///
/// Executes a given operation within the semaphore.
@@ -167,7 +168,37 @@ public static ReentrantSemaphore Create(int initialCount = 1, JoinableTaskContex
///
/// A cancellation token.
/// A task that completes with the result of , after the semaphore has been exited.
- public abstract ValueTask ExecuteAsync(Func> operation, CancellationToken cancellationToken = default);
+ public ValueTask ExecuteAsync(Func> operation, CancellationToken cancellationToken = default)
+ => this.ExecuteValueTaskAsync(operation, null, cancellationToken);
+
+ ///
+ /// Executes a given operation within the semaphore.
+ ///
+ ///
+ /// The delegate to invoke once the semaphore is entered. If a was supplied to the constructor,
+ /// this delegate will execute on the main thread if this is invoked on the main thread, otherwise it will be invoked on the
+ /// threadpool. When no is supplied to the constructor, this delegate will execute on the
+ /// caller's context.
+ ///
+ /// A cancellation token.
+ /// A task that completes with the result of , after the semaphore has been exited.
+ public Task ExecuteAsync(Func