diff --git a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs index c25ad8fbb..9b54f75b7 100644 --- a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs +++ b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs @@ -2253,15 +2253,7 @@ internal interface IInitializeWithWindow [Fact] unsafe public void TestComImports() - { - TestObject(); - GCCollect(); - Assert.Equal(0, ComImports.NumObjects); - - TestImports(); - GCCollect(); - Assert.Equal(0, ComImports.NumObjects); - + { static Object MakeObject() { Assert.Equal(0, ComImports.NumObjects); @@ -2282,25 +2274,25 @@ static Object MakeObject() static void TestImports() { - var (initializeWithWindow, windowNative) = MakeImports(); - - GCCollect(); + var (initializeWithWindow, windowNative) = MakeImports(); + + GC.Collect(); + GC.WaitForPendingFinalizers(); var hwnd = new IntPtr(0x12345678); initializeWithWindow.Initialize(hwnd); Assert.Equal(windowNative.WindowHandle, hwnd); } - static void GCCollect() - { - // Require multiple GC collects due to - // the final release is not done immediately. - for(int idx = 0; idx < 3; idx++) - { - GC.Collect(); - GC.WaitForPendingFinalizers(); - } - } + TestObject(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + Assert.Equal(0, ComImports.NumObjects); + + TestImports(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + Assert.Equal(0, ComImports.NumObjects); } [Fact] diff --git a/src/WinRT.Runtime/ComWrappersSupport.net5.cs b/src/WinRT.Runtime/ComWrappersSupport.net5.cs index a71f4ae1b..003782ec7 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.net5.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.net5.cs @@ -99,12 +99,12 @@ public static T CreateRcwForComObject(IntPtr ptr) winrtObj.Resurrect(); } - return rcw switch - { - ABI.System.Nullable ns => (T)(object)ns.Value, - ABI.System.Nullable nt => (T)(object)nt.Value, - _ => (T)rcw - }; + return rcw switch + { + ABI.System.Nullable ns => (T)(object) ns.Value, + ABI.System.Nullable nt => (T)(object) nt.Value, + _ => (T) rcw + }; } public static bool TryUnwrapObject(object o, out IObjectReference objRef) @@ -143,7 +143,6 @@ public static object TryRegisterObjectForInterface(object obj, IntPtr thisPtr) if (target is IWinRTObject winrtObj) { winrtObj.Resurrect(); - winrtObj.NativeObject.MarkCleanupRCW(); } return rcw; } @@ -206,8 +205,7 @@ public unsafe static void Init( IntPtr inner, out IObjectReference objRef) { - objRef = ComWrappersSupport.GetObjectReferenceForInterface(isAggregation ? inner : newInstance); - objRef.MarkCleanupRCW(); + objRef = ComWrappersSupport.GetObjectReferenceForInterface(isAggregation ? inner : newInstance); IntPtr referenceTracker; { @@ -466,7 +464,6 @@ protected override object CreateObject(IntPtr externalComObject, CreateObjectFla // on destruction as the CLR would do it. winrtObj.NativeObject.ReleaseFromTrackerSource(); winrtObj.NativeObject.PreventReleaseFromTrackerSourceOnDispose = true; - winrtObj.NativeObject.MarkCleanupRCW(); } return obj; diff --git a/src/WinRT.Runtime/IWinRTObject.net5.cs b/src/WinRT.Runtime/IWinRTObject.net5.cs index 3cca966f6..b7431d8f5 100644 --- a/src/WinRT.Runtime/IWinRTObject.net5.cs +++ b/src/WinRT.Runtime/IWinRTObject.net5.cs @@ -169,7 +169,6 @@ internal void Resurrect() { if (NativeObject.Resurrect()) { - NativeObject.MarkCleanupRCW(); foreach (var cached in QueryInterfaceCache) { cached.Value.Resurrect(); diff --git a/src/WinRT.Runtime/ObjectReference.cs b/src/WinRT.Runtime/ObjectReference.cs index 321399fa0..7e5a999b7 100644 --- a/src/WinRT.Runtime/ObjectReference.cs +++ b/src/WinRT.Runtime/ObjectReference.cs @@ -17,8 +17,7 @@ public abstract class IObjectReference : IDisposable protected bool disposed; private readonly IntPtr _thisPtr; private object _disposedLock = new object(); - private IntPtr _referenceTrackerPtr; - private byte _rcwCleanupCounter; + private IntPtr _referenceTrackerPtr; public IntPtr ThisPtr { @@ -196,14 +195,7 @@ protected void ThrowIfDisposed() } public void Dispose() - { - // If this is the object reference associated with the RCW, - // defer dispose to after the RCW has been finalized for .NET 5. - if (!Cleanup) - { - return; - } - + { Dispose(true); GC.SuppressFinalize(this); } @@ -216,20 +208,6 @@ protected virtual void Dispose(bool disposing) { return; } - - // If the object reference is associated with the RCW, we need to - // defer the final release on the ThisPtr until after the RCW has been - // finalized and it has been removed from the ComWrappers cache. - // In .NET 6, there will be a new API for us to use, but until then - // in .NET 5, we defer the finalization of this object until it - // has reached Gen 2 by reregistering for finalization. - if(!Cleanup) - { - _rcwCleanupCounter--; - GC.ReRegisterForFinalize(this); - return; - } - #if DEBUG if (BreakOnDispose && System.Diagnostics.Debugger.IsAttached) { @@ -330,10 +308,6 @@ private unsafe void DisposeTrackerSource() ReferenceTracker.IUnknownVftbl.Release(ReferenceTrackerPtr); } } - - internal void MarkCleanupRCW() => _rcwCleanupCounter = 2; - - private bool Cleanup { get => _rcwCleanupCounter == 0; } } public class ObjectReference : IObjectReference