示例#1
0
            public static void NotifyWhenDeallocated(NSObject obj, Action deallocated)
            {
                // Add an associated object which will be 'released'd when the obj
                // to watch is deallocated. When 'release' is sent, then invoke
                // the 'deallocated' callback.
                var notifier = new ReleaseNotifier(deallocated);

                obj.SetAssociatedObject(IntPtr.Zero, notifier, AssociatedObjects.AssociationPolicy.Retain);
                notifier.Dispose();                  // remove any managed references.
                notifier.enabled = true;             // notify on the next 'release' message.
            }
示例#2
0
        public bool UsableUntilDeadImpl()
        {
            // This test ensure that the main thread can send messages to a garbage collected object,
            // until the final 'release' message for the managed reference has been sent
            // (on the main thread).

            var notifierHandle = IntPtr.Zero;

//			bool isDeallocated = false;
            Action deallocated = () => {
                //Console.WriteLine ("Final release!");
//				isDeallocated = true;
            };

            ManualResetEvent isCollected = new ManualResetEvent(false);
            Action           collected   = () => {
                //Console.WriteLine ("Garbage collected!");
                isCollected.Set();
            };

            bool   isNotified = false;
            Action notified   = () => {
                //Console.WriteLine ("Notified");
                isNotified = true;
            };

            // Create an object whose handle we store in a local variable. We do not
            // store the object itself, since we want the object to be garbage collected.
            var t = new Thread(() => {
                var obj = new Notifier(collected, notified);
                ReleaseNotifier.NotifyWhenDeallocated(obj, deallocated);
                notifierHandle = obj.Handle;
            })
            {
                IsBackground = true,
            };

            t.Start();
            t.Join();

            // Now we have a handle to an object that may be garbage collected at any time.
            int counter = 0;

            do
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
            } while (counter++ < 10 && !isCollected.WaitOne(10));

            // Now we have a handle to a garbage collected object.
            if (!isCollected.WaitOne(0))
            {
                // Objects may randomly not end up collected (at least in Boehm), because
                // other objects may happen to contain a random value pointing to the
                // object we're waiting to become freed.
                return(false);
            }

            // Send a message to the collected object.
            Messaging.void_objc_msgSend(notifierHandle, Selector.GetHandle("notify"));
            Assert.IsTrue(isNotified, "notified");

            // We're done. Cleanup.
            NSRunLoop.Main.RunUntil(NSDate.Now.AddSeconds(0.1));
            // Don't verify cleanup, it's not consistent.
            // And in any case it's not what this test is about.
//			Assert.IsTrue (isDeallocated, "released");

            return(true);
        }