注销事件 MultiCastDelegate 性能问题

Unregister Events MultiCastDelegate Performance Problem

我有一个问题:我们的应用程序已经发展到现在,因此有一个对象有很多很多 EventHandlers。这里的重点是删除它们比添加它们花费更多的时间。这可以很快测试:

  1. 创建一个 class public 事件事件处理器

  2. 第二次报名,第一次报名class 300'000 次。

有趣的一点来了:注册需要大约 0.1 秒,而取消注册需要 5 分钟,而且它几乎呈指数增长。

有人对此有解决方案吗?我发现的唯一一个是通过 WeakEventHandler 解决它(它有缺点),但也许还有另一种可能性。

示例:

  
public class ClassWithValueChangedEvent
  {
    public event EventHandler ValueChanged;
    
    public ClassWithValueChangedEvent()
    {
      
    }
  }

 public class MainWindowViewModel
  {
   
    public MainWindowViewModel()
    {
      DateTime start = DateTime.Now;
      var classInstance = new ClassWithValueChangedEvent();
      for (int i = 0; i < 300000; i++)
      {
        classInstance.ValueChanged += ClassWithValueChangedOnValueChanged;
      }
      Debug.WriteLine($"Elapsed Time: {(DateTime.Now - start).TotalSeconds}");

      start = DateTime.Now;
      for (int i = 0; i < 300000; i++)
      {
        classInstance.ValueChanged -= ClassWithValueChangedOnValueChanged;
      }
      Debug.WriteLine($"Elapsed Time: {(DateTime.Now - start).TotalSeconds}");

如果我们需要删除所有事件处理程序

我要做的是在 class 中创建一个 Unset 方法,使 ValueChanged 事件处理程序无效,如下所示:

public class ClassWithValueChangedEvent
{
    public event EventHandler ValueChanged;

    public void Unset()
    {
        ValueChanged = null;
    }
}

然后,需要的时候我会做:

classInstance.Unset();

这几乎是瞬时的。

如果我们需要删除单个事件处理程序

下面的过程比较复杂,不知道如果有这种需要我会不会选择。这个想法是我们创建一个自定义列表并手动调用处理程序:

public class ClassWithValueChangedEvent
{
    private List<EventHandler> eventHandlers = new List<EventHandler>();

    public void SetEventHandler(EventHandler evt)
    {
        eventHandlers.Add(evt);
    }

    public void UnsetEventHandler(EventHandler evt)
    {
        eventHandlers.Remove(evt);
    }

    public void UnsetAll()
    {
        eventHandlers.Clear();
    }

    public void CallEventHandlers(object? sender, EventArgs e)
    {
        eventHandlers.All(p => { p(sender, e); return true; });
    }
}

那么,这个class的方法可以调用为:

classInstance.SetEventHandler(ClassWithValueChangedOnValueChanged);
classInstance.CallEventHandlers(null, null);
classInstance.UnsetEventHandler(ClassWithValueChangedOnValueChanged);

删除 300000 个事件处理程序大约需要 9 秒,这比几分钟快得多。我也想一定有一种更快的方法来做这样的事情。

我使用 Microsoft 的 WeakEventManager<>.AddHandler() 解决了这个问题,它不会立即删除事件处理程序。在这种情况下没关系。