【问题标题】:When to use Weak Events?何时使用弱事件?
【发布时间】:2012-12-09 15:26:31
【问题描述】:

我在参考 MSDN 教程上的弱事件。我了解了基础知识。我正在从事一个非 WPF 项目,我的班级正在公开某些事件。我的问题是,弱事件 完全取代旧的事件模式?每个暴露事件的类都使用它好吗?随意使用弱事件有什么副作用?

【问题讨论】:

  • 什么都没有被替换,它只是一个 hack,当事件源对象比事件订阅者对象寿命更长并且订阅者对象对取消订阅事件草率时,你会得到一个漏洞。
  • 事件应该总是弱引用...但不幸的是它们不是默认的。 MS 有a class 使用弱引用处理事件,但不幸的是它的语法很糟糕。不过,值得庆幸的是,an event library 为弱事件提供了简单的语法,以及对事件的一些其他改进(例如,对同一事件进行多次发布很简单,消除了不必要的耦合等)

标签: c# .net mef


【解决方案1】:

根据我所做的阅读,使用 Wea​​kEvents 似乎没有任何特定的负面影响,除了这样做更冗长。此外,在大多数情况下,您应该能够在不再需要事件时手动取消注册。在某些情况下,这是不可能的。例如,您引用的 MSDN 页面提到何时应该使用 Wea​​kEvents:

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的handler处理事件
  • 你变成了一个不关心订阅的懒开发者

基本上,它们应该用于您的对象将在其存在的整个期间订阅的事件,并且仅在对象被释放时断开连接。对于其他一切,首选使用传统事件并手动注册/取消注册事件。

【讨论】:

【解决方案2】:

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

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

The Weak Event Pattern is Dangerous查看更多详情。
请参阅此 source code,它使用 MvvMCross 消息传递插件作为弱事件管理器来说明此问题。

【讨论】:

    【解决方案3】:

    何时使用弱事件?

    来自MSDN

    监听事件会导致内存泄漏

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

    每个暴露事件的类都使用它好吗?随意使用弱事件有什么副作用?

    Why is the implementation of events in C# not using a weak event pattern by default?。从“强”事件中泄漏并不常见,弱事件会带来性能成本,并且在每种情况下都可能不希望出现语义差异,滥用弱引用可能会导致事件间歇性地不触发(与滥用正常事件导致内存泄漏)

    可以避免的内存泄漏示例

    静态类和单例在谈论内存泄漏时是恶棍,当它们获得对其他对象的引用时,它们将阻止对象被垃圾收集,因此在应用程序的生命周期内泄漏对象,here 是我遇到了一个需要弱引用以避免内存泄漏的示例

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-08
        相关资源
        最近更新 更多