代码之家  ›  专栏  ›  技术社区  ›  Tormod

对静态实例的事件订阅。如何确保GC

  •  -1
  • Tormod  · 技术社区  · 15 年前

    我正在使用.NET 1.1框架修复用户控制组件。

    此用户控件的许多实例引用了包装COM资源的单例。 他们从这个资源订阅事件。

    我怀疑我们性能下降的原因是因为singleton维护了对用户控制类的引用,即使在它们各自的窗口消失之后。从而阻止GC。

    他们在finalize方法中取消订阅事件。 因此我怀疑是鸡和蛋的问题。Finalize将不会执行,因为它们正通过其事件订阅在寿命更长的单例中引用,从而阻止GC。

    在用户控件中,我应该在哪里执行事件取消订阅以使其符合GC的条件?

    我不拥有承载用户控件的应用程序。

    1 回复  |  直到 15 年前
        1
  •  1
  •   Jon Skeet    15 年前

    实际上,在释放控件时应该取消订阅。如果你不能很容易地修改 Dispose 方法自己,可以将事件处理程序添加到 Disposed 事件:

    ComSingleton.Foo += FooHandler;
    this.Disposed += delegate { ComSingleton.Foo -= FooHandler; };
    

    如果要使用匿名方法或lambda表达式订阅事件,则需要使用单独的局部变量,以便可以再次引用它:

    EventHandler tmp = delegate { Console.WriteLine("Something happened"); };
    ComSingleton.Foo += tmp;
    this.Disposed += delegate { ComSingleton.Foo -= tmp; };
    

    另一种选择是使用“弱事件处理程序”——Web上有很多关于此的文章; here's one 这是相当详细的。