diff --git a/Source/Libs/GLibSharp/ToggleRef.cs b/Source/Libs/GLibSharp/ToggleRef.cs index 20517ac99..432257f69 100644 --- a/Source/Libs/GLibSharp/ToggleRef.cs +++ b/Source/Libs/GLibSharp/ToggleRef.cs @@ -71,8 +71,12 @@ namespace GLib { g_object_unref (handle); else g_object_remove_toggle_ref (handle, ToggleNotifyCallback, (IntPtr) gch); + reference = null; - gch.Free (); + + QueueGCHandleFree (); + + handle = IntPtr.Zero; } internal void Harden () @@ -97,7 +101,8 @@ namespace GLib { reference = new WeakReference (reference); else if (!is_last_ref && reference is WeakReference) { WeakReference weak = reference as WeakReference; - reference = weak.Target; + if (weak.IsAlive) + reference = weak.Target; } } @@ -124,6 +129,37 @@ namespace GLib { } } + static List PendingGCHandleFrees = new List (); + static bool gc_idle_queued; + + public void QueueGCHandleFree () + { + lock (PendingGCHandleFrees) { + PendingGCHandleFrees.Add (gch); + if (!gc_idle_queued){ + Timeout.Add (50, new TimeoutHandler (PerformGCHandleFrees)); + gc_idle_queued = true; + } + } + } + + static bool PerformGCHandleFrees () + { + GCHandle[] handles; + + lock (PendingGCHandleFrees){ + handles = new GCHandle [PendingGCHandleFrees.Count]; + PendingGCHandleFrees.CopyTo (handles, 0); + PendingGCHandleFrees.Clear (); + gc_idle_queued = false; + } + + foreach (GCHandle r in handles) + r.Free (); + + return false; + } + static List PendingDestroys = new List (); static bool idle_queued;