0

是否有任何模式可以让 INotifyPropertyChanged 的​​使用者避免内存泄漏,即使在特定 INotifyPropertyChanged 对象的生命周期内可以创建任意数量的使用者实例的情况下,也不会更改该对象的任何属性(因此通知触发)?事件发布者可以使用一些反射技巧来实现弱事件;是否有任何可行的订阅方弱事件模式?

如果事件合约要求事件发布者必须允许事件订阅者在任何时候从任何线程取消订阅,而不是无限期地阻塞,那么事件订阅者有可能让订阅者真正“感兴趣”的对象保留一个引用包装器对象,并让包装器对象覆盖 Finalize() 以告诉订阅者对象取消订阅。不幸的是,即使订阅者通过 Finalize() 发现它应该取消其订阅,.net 事件合约也不要求发布事件的对象必须允许它们从终结器中安全地释放。事实上,C# 的默认事件实现实际上从终结器中调用是不安全的(当前实现获取发布订阅的对象的锁;如果锁仅用于订阅和取消订阅,那不会有问题,但不能保证在任意时间长度内不会出于其他目的而持有锁)。早期的实现更糟糕:如果一个类尝试订阅或取消订阅它自己的事件,订阅和取消订阅根本就不是线程安全的。

如果知道 INotifyPropertyChanged 对象是某个特定的类,它以线程安全的方式实现其事件(对于订阅,获取锁,然后使用 Interlocked.Exchange 自旋循环;对于取消订阅,使用将获取lock 如果可用,但会尝试 Interlocked.CompareExchange 是否可用)可以安全地删除终结器中的事件处理程序。如果知道该对象会以某种显着频率引发事件,则可能会从事件中删除处理程序(尽管我不确定 .net 事件合同是否要求它也是安全的)。无论什么类型的 INotifyPropertyChanged 实现者被给予观察,是否有任何通用的解决方案可以工作?

编辑——澄清

这个想法不是一个对象会取消订阅它自己的终结器,而是对事件的影响感兴趣的对象将持有对包装对象的引用,事件处理本身不会持有对它的引用。例如,假设目标是计算使用特定事件名称字符串引发 PropertyChanged 事件的次数。可以有一个 PropertyChangeCounter 对象,它持有对 PropertyChangeCounter.Internals 对象的引用;后一个对象将保存事件订阅和更改计数。PropertyChangeCounter 对象的 ChangeCount 属性将返回嵌套 PropertyChangeCounter.Internals ChangeCount 的值。一旦没有外部人员持有对包装器对象的引用,包装器对象将有资格完成,

4

0 回答 0