码迷,mamicode.com
首页 > 其他好文 > 详细

弱引用和弱事件

时间:2014-09-01 19:06:13      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   ar   art   div   

默認對象實例化後得到的都是強引用,不過有時候對於一些複雜的對象,出於性能考慮,并不希望進行頻繁的初始化,此時弱引用就可以派上用場。

用法:先用WeakReference包裝複雜對象,到需要該複雜對象的時候,檢查一下弱引用的IsAlive屬性,如果true,就可以通過Target直接得到複雜對象,省去了實例化的過程。

簡單的例子:

        static void Main(string[] args)
        {
            var weakRef = GetWeakRef();

            GC.Collect();

            if (weakRef.IsAlive)
            {
                var obj = weakRef.Target as ComplexObject;
                Console.WriteLine(obj);
            }
            else
            {
                Console.WriteLine("Reference is not available.");
            }

            Console.Read();
        }

        private static WeakReference GetWeakRef()
        {
            return new WeakReference(new ComplexObject());
        }

本例中如果調用了GC回收,輸出爲

Reference is not available.

如果不調用GC回收,輸出爲

ConsoleApplication1.ComplexObject

       

雖然都是弱,但弱事件的情形卻不太一樣,它的目的在於避免内存泄漏。

普通事件建立了一個發佈者到偵聽者之間的強引用,衹要發佈者存在,偵聽者就無法被回收,即使偵聽者已沒有存在的必要。

内存泄漏的一個簡單例子:

bubuko.com,布布扣
    class Publisher
    {
        public event EventHandler SomeEvent;

        public void RaiseEvent()
        {
            if (SomeEvent != null)
            {
                SomeEvent(this, EventArgs.Empty);
            }
        }
    }

    class Listener
    {
        public void Listener_SomeEvent(object sender, EventArgs e)
        {
            Console.WriteLine("SomeEvent happens");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var pub = new Publisher();
            var lsn = new Listener();

            pub.SomeEvent += lsn.Listener_SomeEvent;
            pub.RaiseEvent();

            lsn = null;
            GC.Collect();

            pub.RaiseEvent();

            Console.Read();
        }
    }   
View Code

程序輸出了兩次SomeEvent happens,説明lsn對象仍然保留在内存中,即使已經將其置空。

 

直接的解決辦法就是:偵聽者主動解除事件訂閲,沒了強引用,自然就可以回收了。 不過有時候難以確定解除事件的時機,此時弱事件就有用場了,它的訣竅在於引入第三方的管理器來間接關聯發佈者和偵聽者,這樣就不會在它們之間建立強引用,從而方便各自的回收。

不過相對於普通的事件偵聽者,弱事件下的偵聽者必須實現IWeakEventListener接口,如下:

   public class Publisher
    {
        public event EventHandler SomeEvent;

        public void RaiseEvent()
        {
            if (SomeEvent != null)
            {
                SomeEvent(this, EventArgs.Empty);
            }
        }
    }

   public class Listener : IWeakEventListener
    {
        public void Listener_SomeEvent(object sender, EventArgs e)
        {
            Console.WriteLine("SomeEvent happens");
        }

        public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
        {
            Listener_SomeEvent(sender, e);
            return true;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var pub = new Publisher();
            var lsn = new Listener();
            WeakEventManager<Publisher, EventArgs>.AddHandler(pub, "SomeEvent", lsn.Listener_SomeEvent);

            pub.RaiseEvent();

            lsn = null;
            GC.Collect();

            pub.RaiseEvent();

            Console.Read();
        }
    }

程序衹會輸出了一次SomeEvent happens,説明lsn確實被回收了。

 

弱引用和弱事件

标签:style   blog   http   color   os   io   ar   art   div   

原文地址:http://www.cnblogs.com/yetsen/p/3949727.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!