事件取消订阅/重新订阅避免内存泄漏

时间:2018-06-28 05:06:23

标签: c# .net memory-leaks

在我们的代码库中,我看到很多与此相似的代码:

void Method()
{
     this.someObject.SomeEvent -= someHandler;
     this.someObject.SomeEvent += someHandler;
     //... other stuff
}

这是否有任何用处? 我一直给实施者带来疑问的好处,以为我可能错过了一些东西。

如果代码类似于:我会理解避免内存泄漏的意图。

void Method()
{
     this.someObject.SomeEvent -= someHandler;
     this.someObject = new WhateverClass();
     this.someObject.SomeEvent += someHandler;
     //... other stuff
}

2 个答案:

答案 0 :(得分:2)

第一个示例是尝试停止可能导致问题(和泄漏)的多个订阅的良性尝试,第二个示例正在尝试阻止内存泄漏

但是,您可以使用具有以下优点的这种模式,它不是阻止泄漏的防弹方法(即,我只是帮助减法,没有多个订阅,并且您没有订阅)不止一次),但它会否定整个加/减操作

private EventHandler _stuff;

public event EventHandler Stuff
{
   add
   {
      if (_stuff== null || !_stuff.GetInvocationList().Contains(value))
         _stuff+= value;
   }
   // ignore the resharper warning
   remove => _stuff -= value;
}

尽管事实是,如果您想使用事件模式,则应该清楚何时需要订阅和取消订阅,如果不需要,则会遇到更大的问题。

个人而言,我更喜欢解耦消息 / 事件聚合器(事物的发布/订阅类型)。这些天,我很少故意创建事件管道。

答案 1 :(得分:1)

仅当您要断言没有绑定到同一事件的重复订阅时,第一种方法才有效。如果您在算法中多次调用Method(),并且someHandler仅被添加而从未从订阅者中删除,那么someHandler回调将被多次调用。那是唯一的风险。

关于内存泄漏,您的推理是完美的。本文介绍了内存泄漏主题。 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-subscribe-to-and-unsubscribe-from-events

祝你愉快