博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
弱引用和弱事件
阅读量:6955 次
发布时间:2019-06-27

本文共 2414 字,大约阅读时间需要 8 分钟。

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

用法:先用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

      

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

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

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

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
.AddHandler(pub, "SomeEvent", lsn.Listener_SomeEvent); pub.RaiseEvent(); lsn = null; GC.Collect(); pub.RaiseEvent(); Console.Read(); } }

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

Net4.5提供了汎型版本的管理器,這樣就不需要自己去實現一個管理器

WeakEventManager<EventSource, SomeEventEventArgs>.AddHandler(source, "SomeEvent", source_SomeEvent);
這樣一行代碼就可以實現一個弱事件

转载于:https://www.cnblogs.com/yetsen/p/4272659.html

你可能感兴趣的文章
简练软考知识点整理-外指赶快先提投降
查看>>
32 MySQL主从
查看>>
HanLP-分类模块的分词器介绍
查看>>
Raid5磁盘阵列修复方法介绍
查看>>
技术解析系列 | PouchContainer 支持 LXCFS 实现高可靠容器隔离
查看>>
linux中web服务器的基本配置
查看>>
linux服务器之间设置ssh免密登录
查看>>
如何将M4A格式的音频转换为MP3格式?只需一步搞定
查看>>
APP项目资源对接平台有那几家
查看>>
微信自定义网页分享链接(可自定义链接 图片 内容介绍)
查看>>
Oracle管理表空间(三)--Oracle UNDO表空间
查看>>
Oracle使用rman进行表空间基于时间点的恢复
查看>>
DNS 多网段的反向记录
查看>>
mac效率工具
查看>>
Oracle imp和exp的使用
查看>>
软件工程---典型用户
查看>>
Acunetix Web Vulnerability Scanner 8.x.x 逆向
查看>>
判断是否是IP地址格式
查看>>
我心目中的牛程序员、我们可以对比看看(人家还是看多年朋友面子上才肯帮忙1周,至少需支付1万元辛苦费)...
查看>>
实际工作中遇到的技术难题与大家交流(工作流条件表达式计算部分),希望技术高手能给于指点...
查看>>