C# 语言 : why WeakReference or Weak Event Pattern?

标签 c# weak-references weak-events

我正在阅读“The C# Language”,第 4 版,它讨论了 WeakReferenceWeak Event Pattern:

CHRISTIAN NAGEL: Memory leaks often result from wrong usage of events. If client objects attach to events but do not detach from them, and the reference to the client object is no longer used, the client object still cannot be reclaimed by the garbage collector because the reference by the publisher remains. This can be avoided by (1) detaching of events when the client object is no longer used, (2) a custom implementation of the add and remove accessors using the WeakReference class holding the delegate, or (3) the Weak Event pattern that is used by WPF with the IWeakEventListener interface.

我在这里有疑问:与“选项 (1) 显式分离事件”相比,选项“(2) WeakReference”根本没有便利,因为使用WeakReference 仍然需要显式调用 addremove

否则,即使事件处理程序的对象之一被分配为 null,“孤立”对象仍将响应该事件 - 这将导致意外行为。

注意:WeakReference 仅以事件处理程序对象不会受到事件发布者对象影响的方式帮助垃圾收集; WeakReference 不会强制事件处理程序对象被垃圾收集。

类似的问题也适用于弱事件模式。

也许这有点抽象,以 Josh Smith 的 Mediator 模式 (http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/) 为例。

public class Mediator //...
{
  public void Register(object message, Action<object> callback)
  {
    // notice: Mediator has no Unregister method
  }
  public void NotifyColleagues(object message, object parameter)
  {
    // ...
  }
}
public class ObjectA //...
{
  public string ObjectAText
  {
    get { return _objectAText; }
    set
    {
      //...
      _mediator.NotifyColleagues(MediatorMessages.ObjectASaidSomething, _objectAText);
    }
  }
}
public class ObjectB //...
{
  //...
  public ObjectB(Mediator mediator)
  {
    //...
    _mediator.Register(
      MediatorMessages.ObjectASaidSomething,
      param =>
      {
        // handling event ObjectASaidSomething
      });
  }
}

如果我们有

ObjectA objectA = new ObjectA();
ObjectB objectB1st = new objectB();
objectA.ObjectAText = "John"; // objectB1st will respond to this event.

objectB1st = null; // due to delay of garbage collection, the object is actually still in memory

ObjectB objectB2nd = new objectB();
objectA.ObjectAText = "Jane"; // both objectB1st and objectB2nd will respond to this event!

由于 WeakReference,最后一行不会导致意外行为吗?

但是如果Mediator类提供了“Unregister”方法(其实我实现了一个),“option (2) WeakReference”和“option (1)没有区别) 明确地分离事件”。 (Mediator 本身仍然是一个有用的模式,可以穿透 WPF 或 MVVM 组件层的层次结构)

最佳答案

如果我明白你在问什么,那么就需要澄清一下。

Otherwise, even if one of the event handler's object was assigned to null, the "orphan" object will still respond to the event - this will cause unexpected behavior.

不是真的。这不是意外行为。如果您不显式取消注册,则完全可以调用该对象。

弱事件的整个想法是一个安全网,它不会仅仅因为对象订阅了一个事件就将它们保留在内存中。当对象超出范围时,它与从事件中注销对象无关。

如果您以后需要执行此操作,请为订阅者使用 IDisposable 模式和“使用”构造,或者显式取消订阅。

即弱事件是针对一个非常具体的问题的解决方案 - 允许对订阅了长生命周期对象(如 GUI 或某些静态类)的对象进行垃圾回收。

弱事件并不是在对象超出范围时自动取消订阅 even。

关于C# 语言 : why WeakReference or Weak Event Pattern?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6653121/

相关文章:

c# - C#解释中的Vigenere算法

c# - OSX Yosemite 10.10 上 Xamarin 中的 PCL 库

c# - 除了一个程序集之外,我如何隐藏所有程序集的 "setters"?

.net - .NET 中的弱事件?

c# - C# 中的 WeakEvent 垃圾回收

silverlight - Silverlight 弱事件的良好实现是什么?

c# - 使用 async/await 设置 Thread.CurrentPrincipal

java - 我是隐藏 WeakReferences 的含义还是强制客户端使用它们

java - 具有 Long、Int 或 String 等类型的 WeakHashMap