diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs index 9df46043178eda..9380337d37f206 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs @@ -1289,7 +1289,7 @@ private static void AddWrapperToReferenceTrackerHandleCache(NativeObjectWrapper private sealed class RcwCache { - private readonly Lock _lock = new Lock(useTrivialWaits: true); + private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); private readonly Dictionary _cache = []; /// @@ -1301,7 +1301,8 @@ private sealed class RcwCache /// The proxy object currently in the cache for or the proxy object owned by if no entry exists and the corresponding native wrapper. public (NativeObjectWrapper actualWrapper, object actualProxy) GetOrAddProxyForComInstance(IntPtr comPointer, NativeObjectWrapper wrapper, object comProxy) { - lock (_lock) + _lock.EnterWriteLock(); + try { Debug.Assert(wrapper.ProxyHandle.Target == comProxy); ref GCHandle rcwEntry = ref CollectionsMarshal.GetValueRefOrAddDefault(_cache, comPointer, out bool exists); @@ -1336,11 +1337,16 @@ private sealed class RcwCache // Return our target object. return (wrapper, comProxy); } + finally + { + _lock.ExitWriteLock(); + } } public object? FindProxyForComInstance(IntPtr comPointer) { - lock (_lock) + _lock.EnterReadLock(); + try { if (_cache.TryGetValue(comPointer, out GCHandle existingHandle)) { @@ -1357,11 +1363,16 @@ private sealed class RcwCache return null; } + finally + { + _lock.ExitReadLock(); + } } public void Remove(IntPtr comPointer, NativeObjectWrapper wrapper) { - lock (_lock) + _lock.EnterWriteLock(); + try { // TryGetOrCreateObjectForComInstanceInternal may have put a new entry into the cache // in the time between the GC cleared the contents of the GC handle but before the @@ -1376,6 +1387,10 @@ public void Remove(IntPtr comPointer, NativeObjectWrapper wrapper) cachedRef.Free(); } } + finally + { + _lock.ExitWriteLock(); + } } }