问题 何时使用弱事件?


我在弱事件上引用了MSDN教程。我理解基础知识。我正在开发一个非WPF项目,我的课程正在暴露某些事件。我的问题是弱事件 完全取代旧的事件模式?每个暴露事件的类都使用它是否好?大量使用弱事件的副作用是什么?


9429
2017-12-09 15:26


起源

没有什么东西可以被替换,只是当事件源对象超过事件订阅者对象并且订阅者对象关于取消订阅事件时,您将获得泄漏。 - Hans Passant
活动 应该 永远是弱引用...但不幸的是,它们不是默认的。 MS有 一类 使用弱引用处理事件,但不幸的是它的语法很残酷。值得庆幸的是,有 一个事件库 这为弱事件提供了简单的语法,以及对事件的一些其他改进 (例如,简单地将多个发布到同一事件,删除不必要的耦合等) - BlueRaja - Danny Pflughoeft


答案:


基于我所做的阅读,使用WeakEvents似乎没有任何具体的负面影响,除了这样做更加冗长的事实。此外,在大多数情况下,您应该能够在不再需要时从事件中手动取消注册。在某些情况下,这是不可能的。例如,您引用的MSDN页面应该在您应该使用WeakEvents时提及:

http://msdn.microsoft.com/en-us/library/aa970850.aspx

某些场景固有地适用于弱事件模式的应用。一种这样的场景是数据绑定。在数据绑定中,源对象通常完全独立于侦听器对象,侦听器对象是绑定的目标。 WPF数据绑定的许多方面已经在事件的实现方式中应用了弱事件模式。

唯一一个向他们提出任何负面影响的人就是这个博客:

http://blog.catenalogic.com/post/2011/11/23/A-weak-event-listener-for-WPF-Silverlight-and-Windows-Phone-7.aspx

一般来说,使用弱事件侦听器有一些缺点:

  • 它的符号很难看,“原始”的.NET方式看起来更好
  • 你必须用字符串命名事件,这很糟糕(如果你知道更好的方法,请联系我!)
  • 它只能使用EventHandler的处理程序处理事件
  • 你成为一个懒惰的开发人员,不关心订阅

从本质上讲,它们应该用于对象将在其存在的整个长度内订阅的事件,并且仅在对象被处置时断开连接。对于其他所有内容,首选使用传统事件并手动注册/取消注册事件。


10
2017-12-09 16:02



第二个链接坏了.. - Rico Suter
是的,看起来原来的网站现在已经变成了kaput。不过,我引用了原始链接中最相关的部分。 - Rob Ocel
这是新链接 catelproject.atlassian.net/wiki/display/CTL/Weak+events - Ismail Hassani
不幸的是,自从回答这个问题以来,发现了一个严重的风险。看到 弱事件模式是危险的,如引用 拉迪的回答。更糟糕的是,风险是不可预测的,根据那篇文章,如果它发生,结果可能是危险的行为,很难找到原因。 - ToolmakerSteve


弱事件必须考虑两个问题:

  1. 弱事件允许订阅者订阅事件(消息),甚至不知道引发事件的类的身份。在某些情况下甚至可能需要。但是,在某些情况下,可能会引入不必要的复杂性和间接性,从而使代码在运行时更难以管理或控制。
  2. 使用弱事件的主要缺点是它可能会鼓励开发人员忽略他们取消订阅事件(消息)的部分。在这种情况下,即使订阅者“超出范围”,也可以调用事件处理程序。考虑一个没有明确取消订阅并且变为垃圾收集但尚未收集垃圾的订阅者。弱事件管理器将无法检测到该状态,因此它仍将调用该订户的事件处理程序。这可能会导致各种意想不到的副作用。

查看更多详情 弱事件模式是危险的
看到这个 源代码 这说明了使用MvvMCross消息传递插件作为弱事件管理器的这个问题。


4
2017-09-20 03:11





什么时候使用弱事件?

MSDN 

侦听事件可能会导致内存泄漏

所以你应该使用弱事件来避免这些泄漏

每个暴露事件的类都使用它是否好?大量使用弱事件的副作用是什么?

看到 为什么C#中的事件实现默认情况下不使用弱事件模式?。从“强”事件中泄漏并非通常情况,弱事件伴随着性能成本并且具有在每种情况下可能都不需要的语义差异,滥用弱参考可能导致事件间歇性地不发射(与之相反)滥用导致内存泄漏的正常事件)

可以避免的内存泄漏示例

在讨论内存泄漏时,静态类和单例是恶棍,当他们获取对其他对象的引用时,它们将阻止对象被垃圾收集,从而在应用程序的生命周期内泄漏对象, 这里 是一个例子,我满足了弱引用的需要,以避免内存泄漏


0
2018-05-07 00:38





首先,弱事件并不总是必要的,就像其他人一直说的那样,只有当源对象比订阅者更长时。如果是这样,那么是的,你应该使用它,这就是人们所说的 弱事件模式

副作用只是你必须编写更多的代码。 Microsoft提供了WeakEventManager类并且在WPF中存在一些特定的实现,但是您可以创建自己继承自WeakEventManager的基础。

它的工作方式是使用 弱参考 从源对象到侦听器,因此这种关系不会阻止GC收集这些对象。对于某些特定应用程序,这可以解决许多性能问题。


0
2018-06-29 22:06