diff --git a/src/csharp/Grpc.Core/Internal/DefaultChannelCredentialsConfigurator.cs b/src/csharp/Grpc.Core/Internal/DefaultChannelCredentialsConfigurator.cs index aaccbdfe6f7..c4c044cd577 100644 --- a/src/csharp/Grpc.Core/Internal/DefaultChannelCredentialsConfigurator.cs +++ b/src/csharp/Grpc.Core/Internal/DefaultChannelCredentialsConfigurator.cs @@ -37,6 +37,7 @@ namespace Grpc.Core.Internal // We rely on finalizer to clean up the native portion of ChannelCredentialsSafeHandle after the ChannelCredentials // instance becomes unused. static readonly ConditionalWeakTable> CachedNativeCredentials = new ConditionalWeakTable>(); + static readonly object StaticLock = new object(); bool configured; ChannelCredentialsSafeHandle nativeCredentials; @@ -93,22 +94,11 @@ namespace Grpc.Core.Internal private ChannelCredentialsSafeHandle GetOrCreateNativeCredentials(ChannelCredentials key, Func nativeCredentialsFactory) { Lazy lazyValue; - while (true) - { - if (CachedNativeCredentials.TryGetValue(key, out lazyValue)) - { - break; - } - - lazyValue = new Lazy(nativeCredentialsFactory); - try + lock (StaticLock) { + if (!CachedNativeCredentials.TryGetValue(key, out lazyValue)) { + lazyValue = new Lazy(nativeCredentialsFactory); CachedNativeCredentials.Add(key, lazyValue); - break; - } - catch (ArgumentException) - { - // key exists, next TryGetValue should fetch the value } } return lazyValue.Value;