diff --git a/Directory.Build.props b/Directory.Build.props
index d60c28751..8a926277d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -21,7 +21,7 @@
$(NoWarn);NETSDK1195;NETSDK1210
true
- 12.0
+ preview
enable
enable
diff --git a/perf/benchmarkapps/QpsWorker/Infrastructure/Histogram.cs b/perf/benchmarkapps/QpsWorker/Infrastructure/Histogram.cs
index b0574893c..2eb689586 100644
--- a/perf/benchmarkapps/QpsWorker/Infrastructure/Histogram.cs
+++ b/perf/benchmarkapps/QpsWorker/Infrastructure/Histogram.cs
@@ -28,7 +28,7 @@ namespace QpsWorker.Infrastructure;
///
public class Histogram
{
- private readonly object _myLock = new object();
+ private readonly Lock _myLock = new Lock();
private readonly double _multiplier;
private readonly double _oneOnLogMultiplier;
private readonly double _maxPossible;
diff --git a/perf/benchmarkapps/QpsWorker/Infrastructure/TimeStats.cs b/perf/benchmarkapps/QpsWorker/Infrastructure/TimeStats.cs
index e3bc0454f..d38a65811 100644
--- a/perf/benchmarkapps/QpsWorker/Infrastructure/TimeStats.cs
+++ b/perf/benchmarkapps/QpsWorker/Infrastructure/TimeStats.cs
@@ -27,7 +27,7 @@ namespace QpsWorker.Infrastructure;
///
public class TimeStats
{
- private readonly object _myLock = new object();
+ private readonly Lock _myLock = new Lock();
private DateTime _lastWallClock;
private TimeSpan _lastUserTime;
private TimeSpan _lastPrivilegedTime;
diff --git a/src/Grpc.AspNetCore.Server/Internal/HttpContextStreamWriter.cs b/src/Grpc.AspNetCore.Server/Internal/HttpContextStreamWriter.cs
index b6a67f9fd..7fd6ab904 100644
--- a/src/Grpc.AspNetCore.Server/Internal/HttpContextStreamWriter.cs
+++ b/src/Grpc.AspNetCore.Server/Internal/HttpContextStreamWriter.cs
@@ -33,7 +33,7 @@ internal class HttpContextStreamWriter : IServerStreamWriter _serializer;
private readonly PipeWriter _bodyWriter;
private readonly IHttpRequestLifetimeFeature _requestLifetimeFeature;
- private readonly object _writeLock;
+ private readonly Lock _writeLock;
private Task? _writeTask;
private bool _completed;
private long _writeCount;
@@ -42,7 +42,7 @@ public HttpContextStreamWriter(HttpContextServerCallContext context, Actiontrue
true
- net462;netstandard2.0;net6.0;net7.0;net8.0
+ net462;netstandard2.0;net6.0;net7.0;net8.0;net9.0
README.md
@@ -26,6 +26,7 @@
+
@@ -33,4 +34,8 @@
+
+
+
+
diff --git a/src/Grpc.HealthCheck/HealthServiceImpl.cs b/src/Grpc.HealthCheck/HealthServiceImpl.cs
index 80003ee68..e02095088 100644
--- a/src/Grpc.HealthCheck/HealthServiceImpl.cs
+++ b/src/Grpc.HealthCheck/HealthServiceImpl.cs
@@ -37,11 +37,11 @@ public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase
// The maximum number of statuses to buffer on the server.
internal const int MaxStatusBufferSize = 5;
- private readonly object statusLock = new object();
+ private readonly Lock statusLock = new Lock();
private readonly Dictionary statusMap =
new Dictionary();
- private readonly object watchersLock = new object();
+ private readonly Lock watchersLock = new Lock();
private readonly Dictionary>> watchers =
new Dictionary>>();
@@ -155,7 +155,8 @@ public override async Task Watch(HealthCheckRequest request, IServerStreamWriter
FullMode = BoundedChannelFullMode.DropOldest
});
- lock (watchersLock)
+ watchersLock.Enter();
+ try
{
if (!watchers.TryGetValue(service, out List>? channelWriters))
{
@@ -165,6 +166,10 @@ public override async Task Watch(HealthCheckRequest request, IServerStreamWriter
channelWriters.Add(channel.Writer);
}
+ finally
+ {
+ watchersLock.Exit();
+ }
// Watch calls run until ended by the client canceling them.
context.CancellationToken.Register(() => {
diff --git a/src/Grpc.Net.Client/Balancer/Internal/BalancerHttpHandler.cs b/src/Grpc.Net.Client/Balancer/Internal/BalancerHttpHandler.cs
index 33bb1d8b5..06f7627e1 100644
--- a/src/Grpc.Net.Client/Balancer/Internal/BalancerHttpHandler.cs
+++ b/src/Grpc.Net.Client/Balancer/Internal/BalancerHttpHandler.cs
@@ -31,7 +31,7 @@ namespace Grpc.Net.Client.Balancer.Internal;
internal class BalancerHttpHandler : DelegatingHandler
{
- private static readonly object SetupLock = new object();
+ private static readonly Lock SetupLock = new Lock();
internal const string WaitForReadyKey = "WaitForReady";
internal const string SubchannelKey = "Subchannel";
diff --git a/src/Grpc.Net.Client/Balancer/Internal/ChildHandlerLoadBalancer.cs b/src/Grpc.Net.Client/Balancer/Internal/ChildHandlerLoadBalancer.cs
index bace88872..f11a40573 100644
--- a/src/Grpc.Net.Client/Balancer/Internal/ChildHandlerLoadBalancer.cs
+++ b/src/Grpc.Net.Client/Balancer/Internal/ChildHandlerLoadBalancer.cs
@@ -1,4 +1,4 @@
-#region Copyright notice and license
+#region Copyright notice and license
// Copyright 2019 The gRPC Authors
//
@@ -53,7 +53,7 @@ internal sealed class ChildHandlerLoadBalancer : LoadBalancer
private readonly IChannelControlHelper _controller;
private readonly ServiceConfig? _initialServiceConfig;
private readonly ConnectionManager _connectionManager;
- private readonly object _lock = new object();
+ private readonly Lock _lock = new Lock();
internal (LoadBalancer LoadBalancer, string Name)? _current;
internal (LoadBalancer LoadBalancer, string Name)? _pending;
diff --git a/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs b/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs
index b64a4557c..51bb0f66f 100644
--- a/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs
+++ b/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs
@@ -30,7 +30,7 @@ internal sealed class ConnectionManager : IDisposable, IChannelControlHelper
public static readonly BalancerAttributesKey HostOverrideKey = new BalancerAttributesKey("HostOverride");
private static readonly ChannelIdProvider _channelIdProvider = new ChannelIdProvider();
- private readonly object _lock;
+ private readonly Lock _lock;
internal readonly Resolver _resolver;
private readonly ISubchannelTransportFactory _subchannelTransportFactory;
private readonly List _subchannels;
@@ -56,7 +56,7 @@ internal ConnectionManager(
ISubchannelTransportFactory subchannelTransportFactory,
LoadBalancerFactory[] loadBalancerFactories)
{
- _lock = new object();
+ _lock = new Lock();
_nextPickerTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
_resolverStartedTcs = new TaskCompletionSource