Explorar o código

Properly handle disposal for Win32 and GTK3

Nikita Tsukanov %!s(int64=8) %!d(string=hai) anos
pai
achega
f6ea72872a

+ 4 - 2
src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs

@@ -75,7 +75,7 @@ namespace Avalonia.Gtk3
 
         private bool OnDestroy(IntPtr gtkwidget, IntPtr userdata)
         {
-            Closed?.Invoke();
+            Dispose();
             return false;
         }
 
@@ -210,7 +210,9 @@ namespace Avalonia.Gtk3
 
         public void Dispose()
         {
-            Closed?.Invoke();
+            //We are calling it here, since signal handler will be detached
+            if (!GtkWidget.IsClosed)
+                Closed?.Invoke();
             foreach(var d in Disposables.AsEnumerable().Reverse())
                 d.Dispose();
             Disposables.Clear();

+ 19 - 9
src/Windows/Avalonia.Win32/WindowImpl.cs

@@ -182,9 +182,18 @@ namespace Avalonia.Win32
 
         public void Dispose()
         {
-            s_instances.Remove(this);
-            _framebuffer.Dispose();
-            UnmanagedMethods.DestroyWindow(_hwnd);
+            _framebuffer?.Dispose();
+            _framebuffer = null;
+            if (_hwnd != IntPtr.Zero)
+            {
+                UnmanagedMethods.DestroyWindow(_hwnd);
+                _hwnd = IntPtr.Zero;
+            }
+            if (_className != null)
+            {
+                UnmanagedMethods.UnregisterClass(_className, UnmanagedMethods.GetModuleHandle(null));
+                _className = null;
+            }
         }
 
         public void Hide()
@@ -418,12 +427,13 @@ namespace Avalonia.Win32
                     return IntPtr.Zero;
 
                 case UnmanagedMethods.WindowsMessage.WM_DESTROY:
-                    if (Closed != null)
-                    {
-                        UnmanagedMethods.UnregisterClass(_className, UnmanagedMethods.GetModuleHandle(null));
-                        Closed();
-                    }
-
+                    //Window doesn't exist anymore
+                    _hwnd = IntPtr.Zero;
+                    //Remove root reference to this class, so unmanaged delegate can be collected
+                    s_instances.Remove(this);
+                    Closed?.Invoke();
+                    //Free other resources
+                    Dispose();
                     return IntPtr.Zero;
 
                 case UnmanagedMethods.WindowsMessage.WM_DPICHANGED: