diff --git a/dotnet/src/webdriver/BiDi/EventStreamExtensions.cs b/dotnet/src/webdriver/BiDi/EventStreamExtensions.cs
new file mode 100644
index 0000000000000..9036d9ba7be89
--- /dev/null
+++ b/dotnet/src/webdriver/BiDi/EventStreamExtensions.cs
@@ -0,0 +1,51 @@
+//
+// Licensed to the Software Freedom Conservancy (SFC) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The SFC licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+using System.Runtime.CompilerServices;
+
+namespace OpenQA.Selenium.BiDi;
+
+public static class EventStreamExtensions
+{
+ ///
+ /// Configures how awaits on the tasks returned from an iteration of the event stream are performed.
+ ///
+ ///
+ ///
+ /// implements both and
+ /// , which makes a plain .ConfigureAwait(bool) call ambiguous
+ /// (CS0121) because TaskAsyncEnumerableExtensions provides an overload for each interface.
+ /// This extension method resolves the ambiguity by explicitly routing to the
+ /// overload, which is the behavior callers need when using
+ /// await foreach.
+ ///
+ ///
+ /// The event-args type produced by the stream.
+ /// The event stream to configure.
+ ///
+ /// to capture and marshal continuation back to the original context;
+ /// to continue on a thread-pool thread.
+ ///
+ /// A configured enumerable that applies the specified context-capture behavior.
+ public static ConfiguredCancelableAsyncEnumerable ConfigureAwait(
+ this IEventStream stream,
+ bool continueOnCapturedContext)
+ where TEventArgs : EventArgs
+ => ((IAsyncEnumerable)stream).ConfigureAwait(continueOnCapturedContext);
+}
diff --git a/dotnet/test/webdriver/BiDi/EventStreamExtensionsTests.cs b/dotnet/test/webdriver/BiDi/EventStreamExtensionsTests.cs
new file mode 100644
index 0000000000000..7a98bfcf714c2
--- /dev/null
+++ b/dotnet/test/webdriver/BiDi/EventStreamExtensionsTests.cs
@@ -0,0 +1,84 @@
+//
+// Licensed to the Software Freedom Conservancy (SFC) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The SFC licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+using System.Runtime.CompilerServices;
+using OpenQA.Selenium.BiDi;
+
+namespace OpenQA.Selenium.Tests.BiDi;
+
+[Parallelizable(ParallelScope.All)]
+[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
+class EventStreamExtensionsTests
+{
+ private IBiDi _bidi;
+ private FakeTransport _transport;
+
+ [SetUp]
+ public async Task SetUp()
+ {
+ _transport = new FakeTransport();
+ _bidi = await Selenium.BiDi.BiDi.ConnectAsync(new Uri("ws://fake"), opts => opts.UseTransport(() => _transport));
+ }
+
+ [TearDown]
+ public async Task TearDown()
+ {
+ await _bidi.DisposeAsync();
+ }
+
+ [Test]
+ public async Task ConfigureAwait_ReturnsConfiguredCancelableAsyncEnumerable()
+ {
+ var stream = await _bidi.Script.RealmDestroyed.StreamAsync()
+ .WithResponse(_transport, """{"subscription":"sub-1"}""");
+
+ // This line previously failed to compile (CS0121) because IEventStream implements
+ // both IAsyncEnumerable and IAsyncDisposable and both have a matching ConfigureAwait overload.
+ // EventStreamExtensions.ConfigureAwait disambiguates toward IAsyncEnumerable.
+ var configured = stream.ConfigureAwait(false);
+
+ Assert.That(configured, Is.InstanceOf>());
+
+ await stream.DisposeAsync().WithResponse(_transport);
+ }
+
+ [Test]
+ public async Task ConfigureAwait_DeliverEventsThroughConfiguredEnumerable()
+ {
+ var stream = await _bidi.Script.RealmDestroyed.StreamAsync()
+ .WithResponse(_transport, """{"subscription":"sub-1"}""");
+
+ _transport.EnqueueEvent("script.realmDestroyed", """{"realm":"r-1"}""");
+
+ var received = new List();
+
+ using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
+
+ await foreach (var e in stream.ConfigureAwait(false).WithCancellation(cts.Token))
+ {
+ received.Add(e);
+ break;
+ }
+
+ Assert.That(received, Has.Count.EqualTo(1));
+ Assert.That(received[0].Realm.Id, Is.EqualTo("r-1"));
+
+ await stream.DisposeAsync().WithResponse(_transport);
+ }
+}