'Unregister Events MultiCastDelegate Performance Problem
I have a problem: Our application has grown so far and therefore there is an object with many many EventHandlers. The point here is that removing them takes far more time, than adding them. This can be tested very fast:
Create a class with a public event EventHandler
Make a second time and register to the event in first class like 300'000 times.
Here comes the interesting point: Registring needs like 0.1 seconds, whereas deregistring needs 5 minutes and it's growing almost exponentially.
Does anyone have a solution for that? The only one I found is to solve it over a WeakEventHandler (with it's downsides), but maybe there is another possiblity.
Example:
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}");
Solution 1:[1]
I solved this question in using the WeakEventManager<>.AddHandler() from microsoft, which does not immediately remove the event handlers. It did not matter in this case.
Solution 2:[2]
If we need to remove all event handlers
What I would do is that I would create an Unset
method inside the class that nullifies the ValueChanged
event handler like bellow:
public class ClassWithValueChangedEvent
{
public event EventHandler ValueChanged;
public void Unset()
{
ValueChanged = null;
}
}
Then, when needed I would do:
classInstance.Unset();
This is almost instantaneous.
If we need to remove individual event handlers
The process bellow is much more complicated and I don't know if I would choose it if I was in such need. The idea is that we create a custom list and we invoke the handlers manually:
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; });
}
}
Then, the methods of this class can be called as:
classInstance.SetEventHandler(ClassWithValueChangedOnValueChanged);
classInstance.CallEventHandlers(null, null);
classInstance.UnsetEventHandler(ClassWithValueChangedOnValueChanged);
Removing 300000 event handlers takes around 9 seconds which is much faster than minutes. I guess also that there must be a much faster way to do something like that.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | C-Sharp Developer |
Solution 2 |