Implementation of a weak event handler.
$ dotnet add package Scotec.Events.WeakEventsThe WeakEventManager class in the Scotec.Events.WeakEvents namespace provides a thread-safe mechanism for managing event subscriptions using weak references. This helps prevent memory leaks that can occur when event handlers are strongly referenced, especially in scenarios where publishers outlive their subscribers.
In .NET, traditional event subscriptions create strong references between the event source and the event handler. If the subscriber is not explicitly unsubscribed, the event source will keep the subscriber alive, potentially causing memory leaks. WeakEventManager solves this by storing event handlers as weak references, allowing the garbage collector to reclaim subscribers when they are no longer in use.
Subscribe to an event using a weak reference:
var manager = new WeakEventManager();
IDisposable remover = manager.AddWeakHandler<MySource, MyEventArgs>( sourceObject, "MyEvent", (src, args) => { /* handle event */ } );
sourceObject: The object that publishes the event."MyEvent": The name of the event to subscribe to.(src, args).You can remove a handler using the returned IDisposable:
remover.Dispose();
Or, remove it directly:
manager.RemoveWeakHandler<MySource, MyEventArgs>( sourceObject, "MyEvent", handler );
To remove handlers whose targets have been garbage collected:
manager.Cleanup();
This can be useful to call periodically, for example, in an event or similar global pause event, to ensure that any unused handlers are removed, and memory can be reclaimed.
Application.Deactivatedmanager.CleanupDeadHandlers();
Dispose the manager to remove all handlers and clean up resources:
manager.Dispose();
For global event management, use the static API:
WeakEventManager.AddWeakHandler<MySource, MyEventArgs>( sourceObject, "MyEvent", (src, args) => { /* handle event */ } );
AddWeakHandler<TObject, TEventArgs>(TObject source, string eventName, Action<TObject, TEventArgs> handler): Registers a weak event handler and returns an IDisposable for manual removal.RemoveWeakHandler<TObject, TEventArgs>(TObject source, string eventName, Action<TObject, TEventArgs> handler): Removes a previously registered weak event handler.CleanupDeadHandlers(): Removes handlers whose targets have been garbage collected.Dispose(): Removes all handlers and releases resources.public class MySource
{
public event EventHandler<MyEventArgs> MyEvent;
}
public class MySubscriber
{
public void Subscribe(MySource source, WeakEventManager manager)
{
manager.AddWeakHandler<MySource, MyEventArgs>( source, nameof(source.MyEvent), (src, args) => HandleEvent(args) );
}
private void HandleEvent(MySource source, MyEventArgs args)
{
// Handle event logic
}
}
See LICENSE for details.
For more information, see the source code in Scotec.Events.WeakEvents\WeakEventManager.cs