关于事件注销的问题。

时间:2022-08-30 14:18:42
我在一个对象里面注册了个事件,然后当这个对象不再被引用的话是不是 会自动被GC回收,包括对象里的监听事件?
我不知道是不是需要手动注销事件。就算手动注销事件也没有一个入口可以提供我去注销事件的呀。请了解的朋友们给个建议吧。谢谢。

11 个解决方案

#1


+= 是事件绑定。 -= 就是取消事件绑定。
我建议你析构函数里或者其他关闭函数里调用取消事件绑定,因为我之前碰到过诡异的事件,你不取消绑定有可能会调用这个事件。

#2


一般不用特意去注销(反正我没注销过),注册是+=,注销就是-=

#3


事件是依赖倒置机制,也就是说,对象 A 的事件被 B 对象监听,此时 A 并不依赖于 B,相反地B依赖于 A。A将消息通知给B,但是A并不依赖B,相反地事件触发类型定义了事件接口(而不是事件接收方来定义接口)。

对于 GC 来说,只要B依赖于A 则需要先释放A,但是A并没有依赖所以可以释放。

假设作为服务的 A 对象并不释放,但是你希望能够让 GC 去释放那个看起来是客户对象的 B,那么你就需要“注销事件”,否则就会因为事件的倒置依赖关系而产生内存泄漏。

#4


如果被监听的对象存在,这个监听的对象是不会回收的
如果需要个入口的话就是在你移除该对象的时候

#5


事件造成的内存泄漏比较容易忽视,即使是纠结于概念,也并不容易想当然地就避免。而所谓的一些“弱引用事件”的做法显然有比较大的性能损失。

所以最好的办法是“埋桩”测试。当你销毁一个对象(不管是简单组件,还是复杂容器组件)之前,可以使用你的测试程序的一个“弱引用”来引用它,然后当它理论上失去联系(几秒钟后应该自动被 GC销毁)之后,1分钟之后查看此弱引用,来判断所引用的对象是否真的已经不存在了。弱引用应该用于测试程序设计,而不是用在实际生产程序中。

#6


理论好讲,但是知道 What 的人往往并不能知道 How,讲理论经常都是言行不一的。

所以你需要亲自写测试,特别是最好能用在日常的开发中(你的100个测试用例中总应该有2、3个专门针对内存泄漏进行测试的),自己亲自写出测试来,你才能说自己真的有谱了。

#7


我再强调一遍,我看到你的问题的提问方式,只知道求人、照抄,让你设计一个机制来判断“如果不手动注销,会不会产生什么问题”可能你就脑筋懒得动一动了。

抄点代码容易,但是自己亲自动手写测试来“否定之否定”地测验它,这才是真正的技术。会建立一个东西之前,你也要会破坏、毁掉一个东西。如果只会照抄书上的,那么就成了中小学生的思维习惯了,而不是成年人了。

#8


引用 3 楼 sp1234 的回复:
事件是依赖倒置机制,也就是说,对象 A 的事件被 B 对象监听,此时 A 并不依赖于 B,相反地B依赖于 A。A将消息通知给B,但是A并不依赖B,相反地事件触发类型定义了事件接口(而不是事件接收方来定义接口)。

对于 GC 来说,只要B依赖于A 则需要先释放A,但是A并没有依赖所以可以释放。

假设作为服务的 A 对象并不释放,但是你希望能够让 GC 去释放那个看起来是客户对象的 B,那么你就需要“注销事件”,否则就会因为事件的倒置依赖关系而产生内存泄漏。

只有监听对象B才有+=和-=操作 显而易见 B 是主动 且依赖被引用对象A,如果不引用到A, A就根本不会在内存里有开销。
我按照你后面说的方法自己去测测, 我的B对象是动态加载的C 对象里的一个成员事件句柄。我看看我的C 对象失去引用后 是不是会有B对象保持对A 的监听。

#9


引用 2 楼 yuankaiwsl 的回复:
一般不用特意去注销(反正我没注销过),注册是+=,注销就是-=

你是来打酱油的吧 关于事件注销的问题。

#10


引用 7 楼 sp1234 的回复:
抄点代码容易,但是自己亲自动手写测试来“否定之否定”地测验它,这才是真正的技术。会建立一个东西之前,你也要会破坏、毁掉一个东西。如果只会照抄书上的,那么就成了中小学生的思维习惯了,而不是成年人了。

有些话说的对,有些就不对了。大多数人一开始的时候是从抄开始的。只要不要一直抄下去就行了。
就是有问题觉得抄不是办法才来发帖问的,好了你一说我自己去测了。

#11


引用 9 楼 zmidl 的回复:
Quote: 引用 2 楼 yuankaiwsl 的回复:

一般不用特意去注销(反正我没注销过),注册是+=,注销就是-=

你是来打酱油的吧 关于事件注销的问题。
事件解绑(-=),我真没有用过,也没出想过问题,看样子我写的代码都是一般情况,特殊情况没遇到过

#1


+= 是事件绑定。 -= 就是取消事件绑定。
我建议你析构函数里或者其他关闭函数里调用取消事件绑定,因为我之前碰到过诡异的事件,你不取消绑定有可能会调用这个事件。

#2


一般不用特意去注销(反正我没注销过),注册是+=,注销就是-=

#3


事件是依赖倒置机制,也就是说,对象 A 的事件被 B 对象监听,此时 A 并不依赖于 B,相反地B依赖于 A。A将消息通知给B,但是A并不依赖B,相反地事件触发类型定义了事件接口(而不是事件接收方来定义接口)。

对于 GC 来说,只要B依赖于A 则需要先释放A,但是A并没有依赖所以可以释放。

假设作为服务的 A 对象并不释放,但是你希望能够让 GC 去释放那个看起来是客户对象的 B,那么你就需要“注销事件”,否则就会因为事件的倒置依赖关系而产生内存泄漏。

#4


如果被监听的对象存在,这个监听的对象是不会回收的
如果需要个入口的话就是在你移除该对象的时候

#5


事件造成的内存泄漏比较容易忽视,即使是纠结于概念,也并不容易想当然地就避免。而所谓的一些“弱引用事件”的做法显然有比较大的性能损失。

所以最好的办法是“埋桩”测试。当你销毁一个对象(不管是简单组件,还是复杂容器组件)之前,可以使用你的测试程序的一个“弱引用”来引用它,然后当它理论上失去联系(几秒钟后应该自动被 GC销毁)之后,1分钟之后查看此弱引用,来判断所引用的对象是否真的已经不存在了。弱引用应该用于测试程序设计,而不是用在实际生产程序中。

#6


理论好讲,但是知道 What 的人往往并不能知道 How,讲理论经常都是言行不一的。

所以你需要亲自写测试,特别是最好能用在日常的开发中(你的100个测试用例中总应该有2、3个专门针对内存泄漏进行测试的),自己亲自写出测试来,你才能说自己真的有谱了。

#7


我再强调一遍,我看到你的问题的提问方式,只知道求人、照抄,让你设计一个机制来判断“如果不手动注销,会不会产生什么问题”可能你就脑筋懒得动一动了。

抄点代码容易,但是自己亲自动手写测试来“否定之否定”地测验它,这才是真正的技术。会建立一个东西之前,你也要会破坏、毁掉一个东西。如果只会照抄书上的,那么就成了中小学生的思维习惯了,而不是成年人了。

#8


引用 3 楼 sp1234 的回复:
事件是依赖倒置机制,也就是说,对象 A 的事件被 B 对象监听,此时 A 并不依赖于 B,相反地B依赖于 A。A将消息通知给B,但是A并不依赖B,相反地事件触发类型定义了事件接口(而不是事件接收方来定义接口)。

对于 GC 来说,只要B依赖于A 则需要先释放A,但是A并没有依赖所以可以释放。

假设作为服务的 A 对象并不释放,但是你希望能够让 GC 去释放那个看起来是客户对象的 B,那么你就需要“注销事件”,否则就会因为事件的倒置依赖关系而产生内存泄漏。

只有监听对象B才有+=和-=操作 显而易见 B 是主动 且依赖被引用对象A,如果不引用到A, A就根本不会在内存里有开销。
我按照你后面说的方法自己去测测, 我的B对象是动态加载的C 对象里的一个成员事件句柄。我看看我的C 对象失去引用后 是不是会有B对象保持对A 的监听。

#9


引用 2 楼 yuankaiwsl 的回复:
一般不用特意去注销(反正我没注销过),注册是+=,注销就是-=

你是来打酱油的吧 关于事件注销的问题。

#10


引用 7 楼 sp1234 的回复:
抄点代码容易,但是自己亲自动手写测试来“否定之否定”地测验它,这才是真正的技术。会建立一个东西之前,你也要会破坏、毁掉一个东西。如果只会照抄书上的,那么就成了中小学生的思维习惯了,而不是成年人了。

有些话说的对,有些就不对了。大多数人一开始的时候是从抄开始的。只要不要一直抄下去就行了。
就是有问题觉得抄不是办法才来发帖问的,好了你一说我自己去测了。

#11


引用 9 楼 zmidl 的回复:
Quote: 引用 2 楼 yuankaiwsl 的回复:

一般不用特意去注销(反正我没注销过),注册是+=,注销就是-=

你是来打酱油的吧 关于事件注销的问题。
事件解绑(-=),我真没有用过,也没出想过问题,看样子我写的代码都是一般情况,特殊情况没遇到过