Skip to content

[browser][mt] Thread affinity for HTTP and WS #85244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal static partial class X509ResourceClient

try
{
ret = await s_downloadBytes(uri, cts?.Token ?? default, async).ConfigureAwait(false);
ret = await s_downloadBytes(uri, cts?.Token ?? default, async).ConfigureAwait(OperatingSystem.IsBrowser());
return ret;
}
catch { }
Expand Down Expand Up @@ -163,7 +163,7 @@ internal static partial class X509ResourceClient
if (async)
{
Task sendTask = (Task)sendAsyncMethod.Invoke(httpClient, new object[] { requestMessage, cancellationToken })!;
await sendTask.ConfigureAwait(false);
await sendTask.ConfigureAwait(OperatingSystem.IsBrowser());
responseMessage = taskOfHttpResponseMessageResultProp.GetValue(sendTask)!;
}
else
Expand Down Expand Up @@ -207,7 +207,7 @@ internal static partial class X509ResourceClient
if (async)
{
Task sendTask = (Task)sendAsyncMethod.Invoke(httpClient, new object[] { requestMessage, cancellationToken })!;
await sendTask.ConfigureAwait(false);
await sendTask.ConfigureAwait(OperatingSystem.IsBrowser());
responseMessage = taskOfHttpResponseMessageResultProp.GetValue(sendTask)!;
}
else
Expand All @@ -229,7 +229,7 @@ internal static partial class X509ResourceClient
var result = new MemoryStream();
if (async)
{
await responseStream.CopyToAsync(result).ConfigureAwait(false);
await responseStream.CopyToAsync(result).ConfigureAwait(OperatingSystem.IsBrowser());
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/Common/src/System/Net/StreamBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken
}

buffer = buffer.Slice(bytesWritten);
await _writeTaskSource.WaitAsync(cancellationToken).ConfigureAwait(false);
await _writeTaskSource.WaitAsync(cancellationToken).ConfigureAwait(OperatingSystem.IsBrowser());
}
}

Expand Down Expand Up @@ -243,7 +243,7 @@ public async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken can
if (wait)
{
Debug.Assert(bytesRead == 0);
await _readTaskSource.WaitAsync(cancellationToken).ConfigureAwait(false);
await _readTaskSource.WaitAsync(cancellationToken).ConfigureAwait(OperatingSystem.IsBrowser());
(wait, bytesRead) = TryReadFromBuffer(buffer.Span);
Debug.Assert(!wait);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static async ValueTask InvokeAsync<TState>(Action<TState> action, TState
// Register for cancellation, perform the work, and clean up. Even though we're in an async method, awaits _must not_ be used inside
// the using block, or else the I/O cancellation could both not work and negatively interact with I/O on another thread. The func
// _must_ be invoked on the same thread that invoked RegisterCancellation, with no intervening work.
await using (workItem.RegisterCancellation(cancellationToken).ConfigureAwait(false))
await using (workItem.RegisterCancellation(cancellationToken).ConfigureAwait(OperatingSystem.IsBrowser()))
{
try
{
Expand Down Expand Up @@ -116,7 +116,7 @@ public static async ValueTask<TResult> InvokeAsync<TState, TResult>(Func<TState,
// Register for cancellation, perform the work, and clean up. Even though we're in an async method, awaits _must not_ be used inside
// the using block, or else the I/O cancellation could both not work and negatively interact with I/O on another thread. The func
// _must_ be invoked on the same thread that invoked RegisterCancellation, with no intervening work.
await using (workItem.RegisterCancellation(cancellationToken).ConfigureAwait(false))
await using (workItem.RegisterCancellation(cancellationToken).ConfigureAwait(OperatingSystem.IsBrowser()))
{
try
{
Expand Down Expand Up @@ -188,13 +188,13 @@ public async ValueTask DisposeAsync()
// Then we need to dispose of the registration. Upon Dispose returning, we know that
// either the synchronous invocation of the callback completed or that the callback
// will never be invoked.
await CancellationRegistration.DisposeAsync().ConfigureAwait(false);
await CancellationRegistration.DisposeAsync().ConfigureAwait(OperatingSystem.IsBrowser());

// Now that we know the synchronous callback has quiesced, check to see whether it scheduled
// asynchronous work. If it did, wait for that work to complete.
if (WorkItem.CallbackCompleted is Task t)
{
await t.ConfigureAwait(false);
await t.ConfigureAwait(OperatingSystem.IsBrowser());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public async ValueTask<T> WaitWithCancellationAsync(CancellationToken cancellati
{
using (cancellationToken.UnsafeRegister(static (s, cancellationToken) => ((TaskCompletionSourceWithCancellation<T>)s!).TrySetCanceled(cancellationToken), this))
{
return await Task.ConfigureAwait(false);
return await Task.ConfigureAwait(OperatingSystem.IsBrowser());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public static Task<TResult> WaitAsync<TResult>(this Task<TResult> task, TimeSpan
#else
public static async Task<TResult> WaitAsync<TResult>(this Task<TResult> task, TimeSpan timeout, TimeProvider timeProvider, CancellationToken cancellationToken = default)
{
await ((Task)task).WaitAsync(timeout, timeProvider, cancellationToken).ConfigureAwait(false);
await ((Task)task).WaitAsync(timeout, timeProvider, cancellationToken).ConfigureAwait(OperatingSystem.IsBrowser());
return task.Result;
}
#endif // NET8_0_OR_GREATER
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public static void SetString(this IDistributedCache cache, string key, string va
/// <returns>A task that gets the string value from the stored cache key.</returns>
public static async Task<string?> GetStringAsync(this IDistributedCache cache, string key, CancellationToken token = default(CancellationToken))
{
byte[]? data = await cache.GetAsync(key, token).ConfigureAwait(false);
byte[]? data = await cache.GetAsync(key, token).ConfigureAwait(OperatingSystem.IsBrowser());
if (data == null)
{
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value,
{
using ICacheEntry entry = cache.CreateEntry(key);

result = await factory(entry).ConfigureAwait(false);
result = await factory(entry).ConfigureAwait(OperatingSystem.IsBrowser());
entry.Value = result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public ValueTask DisposeAsync()

static async ValueTask Await(int i, ValueTask vt, List<object> toDispose)
{
await vt.ConfigureAwait(false);
await vt.ConfigureAwait(OperatingSystem.IsBrowser());
// vt is acting on the disposable at index i,
// decrement it and move to the next iteration
i--;
Expand All @@ -160,7 +160,7 @@ static async ValueTask Await(int i, ValueTask vt, List<object> toDispose)
object disposable = toDispose[i];
if (disposable is IAsyncDisposable asyncDisposable)
{
await asyncDisposable.DisposeAsync().ConfigureAwait(false);
await asyncDisposable.DisposeAsync().ConfigureAwait(OperatingSystem.IsBrowser());
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public virtual async Task StopAsync(CancellationToken cancellationToken)
var tcs = new TaskCompletionSource<object>();
using CancellationTokenRegistration registration = cancellationToken.Register(s => ((TaskCompletionSource<object>)s!).SetCanceled(), tcs);
// Do not await the _executeTask because cancelling it will throw an OperationCanceledException which we are explicitly ignoring
await Task.WhenAny(_executeTask, tcs.Task).ConfigureAwait(false);
await Task.WhenAny(_executeTask, tcs.Task).ConfigureAwait(OperatingSystem.IsBrowser());
}

}
Expand Down
28 changes: 14 additions & 14 deletions src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
using var combinedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _applicationLifetime.ApplicationStopping);
CancellationToken combinedCancellationToken = combinedCancellationTokenSource.Token;

await _hostLifetime.WaitForStartAsync(combinedCancellationToken).ConfigureAwait(false);
await _hostLifetime.WaitForStartAsync(combinedCancellationToken).ConfigureAwait(OperatingSystem.IsBrowser());

combinedCancellationToken.ThrowIfCancellationRequested();
_hostedServices = Services.GetRequiredService<IEnumerable<IHostedService>>();
Expand All @@ -72,7 +72,7 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
{
Task tasks = Task.WhenAll(_hostedServices.Select(async service =>
{
await service.StartAsync(combinedCancellationToken).ConfigureAwait(false);
await service.StartAsync(combinedCancellationToken).ConfigureAwait(OperatingSystem.IsBrowser());

if (service is BackgroundService backgroundService)
{
Expand All @@ -82,7 +82,7 @@ public async Task StartAsync(CancellationToken cancellationToken = default)

try
{
await tasks.ConfigureAwait(false);
await tasks.ConfigureAwait(OperatingSystem.IsBrowser());
}
catch (Exception ex)
{
Expand All @@ -96,7 +96,7 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
try
{
// Fire IHostedService.Start
await hostedService.StartAsync(combinedCancellationToken).ConfigureAwait(false);
await hostedService.StartAsync(combinedCancellationToken).ConfigureAwait(OperatingSystem.IsBrowser());

if (hostedService is BackgroundService backgroundService)
{
Expand Down Expand Up @@ -145,7 +145,7 @@ private async Task TryExecuteBackgroundServiceAsync(BackgroundService background

try
{
await backgroundTask.ConfigureAwait(false);
await backgroundTask.ConfigureAwait(OperatingSystem.IsBrowser());
}
catch (Exception ex)
{
Expand Down Expand Up @@ -185,11 +185,11 @@ public async Task StopAsync(CancellationToken cancellationToken = default)

if (_options.ServicesStopConcurrently)
{
Task tasks = Task.WhenAll(hostedServices.Select(async service => await service.StopAsync(token).ConfigureAwait(false)));
Task tasks = Task.WhenAll(hostedServices.Select(async service => await service.StopAsync(token).ConfigureAwait(OperatingSystem.IsBrowser())));

try
{
await tasks.ConfigureAwait(false);
await tasks.ConfigureAwait(OperatingSystem.IsBrowser());
}
catch (Exception ex)
{
Expand All @@ -202,7 +202,7 @@ public async Task StopAsync(CancellationToken cancellationToken = default)
{
try
{
await hostedService.StopAsync(token).ConfigureAwait(false);
await hostedService.StopAsync(token).ConfigureAwait(OperatingSystem.IsBrowser());
}
catch (Exception ex)
{
Expand All @@ -217,7 +217,7 @@ public async Task StopAsync(CancellationToken cancellationToken = default)

try
{
await _hostLifetime.StopAsync(token).ConfigureAwait(false);
await _hostLifetime.StopAsync(token).ConfigureAwait(OperatingSystem.IsBrowser());
}
catch (Exception ex)
{
Expand Down Expand Up @@ -253,25 +253,25 @@ public async ValueTask DisposeAsync()
if (ReferenceEquals(_hostEnvironment.ContentRootFileProvider, _defaultProvider))
{
// Dispose the content provider
await DisposeAsync(_hostEnvironment.ContentRootFileProvider).ConfigureAwait(false);
await DisposeAsync(_hostEnvironment.ContentRootFileProvider).ConfigureAwait(OperatingSystem.IsBrowser());
}
else
{
// In the rare case that the user replaced the ContentRootFileProvider, dispose it and the one
// we originally created
await DisposeAsync(_hostEnvironment.ContentRootFileProvider).ConfigureAwait(false);
await DisposeAsync(_defaultProvider).ConfigureAwait(false);
await DisposeAsync(_hostEnvironment.ContentRootFileProvider).ConfigureAwait(OperatingSystem.IsBrowser());
await DisposeAsync(_defaultProvider).ConfigureAwait(OperatingSystem.IsBrowser());
}

// Dispose the service provider
await DisposeAsync(Services).ConfigureAwait(false);
await DisposeAsync(Services).ConfigureAwait(OperatingSystem.IsBrowser());

static async ValueTask DisposeAsync(object o)
{
switch (o)
{
case IAsyncDisposable asyncDisposable:
await asyncDisposable.DisposeAsync().ConfigureAwait(false);
await asyncDisposable.DisposeAsync().ConfigureAwait(OperatingSystem.IsBrowser());
break;
case IDisposable disposable:
disposable.Dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ async Task<HttpResponseMessage> Core(HttpRequestMessage request, CancellationTok
// not really anything to surround.
Log.RequestStart(_logger, request, shouldRedactHeaderValue);
var stopwatch = ValueStopwatch.StartNew();
HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(OperatingSystem.IsBrowser());
Log.RequestEnd(_logger, response, stopwatch.GetElapsedTime(), shouldRedactHeaderValue);

return response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async Task<HttpResponseMessage> Core(HttpRequestMessage request, CancellationTok
using (Log.BeginRequestPipelineScope(_logger, request))
{
Log.RequestPipelineStart(_logger, request, shouldRedactHeaderValue);
HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(OperatingSystem.IsBrowser());
Log.RequestPipelineEnd(_logger, response, stopwatch.GetElapsedTime(), shouldRedactHeaderValue);

return response;
Expand Down
Loading