注销事件 MultiCastDelegate 性能问题
Unregister Events MultiCastDelegate Performance Problem
我有一个问题:我们的应用程序已经发展到现在,因此有一个对象有很多很多 EventHandlers。这里的重点是删除它们比添加它们花费更多的时间。这可以很快测试:
创建一个 class
public 事件事件处理器
第二次报名,第一次报名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() 解决了这个问题,它不会立即删除事件处理程序。在这种情况下没关系。
我有一个问题:我们的应用程序已经发展到现在,因此有一个对象有很多很多 EventHandlers。这里的重点是删除它们比添加它们花费更多的时间。这可以很快测试:
创建一个 class public 事件事件处理器
第二次报名,第一次报名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() 解决了这个问题,它不会立即删除事件处理程序。在这种情况下没关系。