Scotec.Events.WeakEvents
1.1.1-dev.12
dotnet add package Scotec.Events.WeakEvents --version 1.1.1-dev.12
NuGet\Install-Package Scotec.Events.WeakEvents -Version 1.1.1-dev.12
<PackageReference Include="Scotec.Events.WeakEvents" Version="1.1.1-dev.12" />
<PackageVersion Include="Scotec.Events.WeakEvents" Version="1.1.1-dev.12" />
<PackageReference Include="Scotec.Events.WeakEvents" />
paket add Scotec.Events.WeakEvents --version 1.1.1-dev.12
#r "nuget: Scotec.Events.WeakEvents, 1.1.1-dev.12"
#:package Scotec.Events.WeakEvents@1.1.1-dev.12
#addin nuget:?package=Scotec.Events.WeakEvents&version=1.1.1-dev.12&prerelease
#tool nuget:?package=Scotec.Events.WeakEvents&version=1.1.1-dev.12&prerelease
WeakEventManager
The 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.
Purpose
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.
Features
- Add weak event handlers for any event on any object.
- Remove weak event handlers manually or automatically when the target is collected.
- Automatic cleanup of dead handlers.
- Thread-safe management of event handler delegates.
- Disposable remover for easy unsubscription.
- Static API for global weak event management.
Usage
1. Adding a Weak Event Handler (Instance)
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.- Handler: A lambda or method matching
(src, args).
2. Removing a Weak Event Handler
You can remove a handler using the returned IDisposable:
remover.Dispose();
Or, remove it directly:
manager.RemoveWeakHandler<MySource, MyEventArgs>( sourceObject, "MyEvent", handler );
3. Cleaning Up Dead Handlers
To remove handlers whose targets have been garbage collected:
manager.Cleanup();
This can be useful to call periodically, for example, in an Application.Deactivated event or similar global pause event, to ensure that any unused handlers are removed, and memory can be reclaimed.
manager.CleanupDeadHandlers();
4. Disposing the Manager
Dispose the manager to remove all handlers and clean up resources:
manager.Dispose();
5. Static Usage
For global event management, use the static API:
WeakEventManager.AddWeakHandler<MySource, MyEventArgs>( sourceObject, "MyEvent", (src, args) => { /* handle event */ } );
API Reference
AddWeakHandler<TObject, TEventArgs>(TObject source, string eventName, Action<TObject, TEventArgs> handler): Registers a weak event handler and returns anIDisposablefor 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.
Example
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
}
}
When to Use
- To avoid memory leaks from event subscriptions.
- In MVVM, UI, or long-lived publisher scenarios.
- When subscribers may be short-lived or dynamically created.
Notes
- The event name must match the actual event on the source object.
- Only events with compatible delegate signatures are supported.
- The manager is thread-safe.
- Compatible with .NET Standard 2.0 and 2.1.
License
See LICENSE for details.
For more information, see the source code in Scotec.Events.WeakEvents\WeakEventManager.cs
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
.NETStandard 2.1
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Scotec.Events.WeakEvents:
| Package | Downloads |
|---|---|
|
Scotec.XmlDatabase
Wrapper for XML files that supports transactional operations. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.1-dev.12 | 172 | 11/27/2025 |
| 1.1.1-dev.11 | 147 | 11/25/2025 |
| 1.1.1-dev.10 | 139 | 11/25/2025 |
| 1.1.1-dev.9 | 138 | 11/25/2025 |
| 1.1.1-dev.5 | 251 | 11/21/2025 |
| 1.1.0 | 445 | 11/18/2025 |
| 1.0.9 | 450 | 11/18/2025 |
| 1.0.9-dev.15 | 186 | 9/22/2025 |
| 1.0.9-dev.13 | 151 | 8/30/2025 |
| 1.0.9-dev.10 | 66 | 7/19/2025 |
| 1.0.9-dev.8 | 138 | 7/17/2025 |
| 1.0.9-dev.6 | 141 | 7/16/2025 |
| 1.0.9-dev.5 | 141 | 7/16/2025 |
| 1.0.9-dev.4 | 140 | 7/16/2025 |
| 1.0.9-dev.3 | 144 | 7/16/2025 |
| 1.0.8 | 609 | 3/25/2025 |
| 1.0.8-dev.2 | 206 | 3/4/2025 |
| 1.0.8-dev.1 | 212 | 3/4/2025 |
| 1.0.7 | 238 | 1/24/2025 |
| 1.0.6 | 225 | 1/10/2025 |
| 1.0.5 | 218 | 1/10/2025 |
| 1.0.5-dev.6 | 104 | 12/26/2024 |
| 1.0.4 | 239 | 11/25/2024 |
| 1.0.3 | 311 | 9/13/2024 |
| 1.0.2-dev.5 | 130 | 9/13/2024 |
| 1.0.2-dev.4 | 117 | 9/13/2024 |
| 1.0.2-dev.3 | 110 | 9/13/2024 |
| 1.0.2-dev.2 | 129 | 9/13/2024 |
| 1.0.1 | 364 | 7/14/2024 |
| 1.0.1-dev.6 | 104 | 9/13/2024 |
| 1.0.1-dev.1 | 153 | 1/14/2024 |
| 1.0.0 | 877 | 1/1/2024 |
| 1.0.0-dev.28 | 120 | 1/1/2024 |
| 0.9.4-dev.23 | 124 | 12/29/2023 |
| 0.9.4-dev.20 | 168 | 11/9/2023 |
| 0.9.4-dev.15 | 124 | 9/28/2023 |
| 0.9.4-dev.14 | 113 | 9/28/2023 |
| 0.9.4-dev.9 | 127 | 9/23/2023 |
| 0.9.4-dev.8 | 127 | 9/22/2023 |
| 0.9.3 | 328 | 9/1/2023 |
| 0.9.3-dev.102 | 125 | 9/22/2023 |
| 0.9.3-dev.101 | 146 | 9/22/2023 |
| 0.9.3-dev.92 | 139 | 8/23/2023 |
| 0.9.3-dev.70 | 191 | 3/18/2023 |
| 0.9.3-dev.69 | 195 | 3/18/2023 |
| 0.9.3-dev.67 | 188 | 3/18/2023 |
| 0.9.3-dev.66 | 190 | 3/18/2023 |
| 0.9.3-dev.64 | 190 | 3/6/2023 |
| 0.9.3-dev.62 | 183 | 2/17/2023 |
| 0.9.3-dev.61 | 186 | 2/17/2023 |
| 0.9.3-dev.58 | 195 | 2/17/2023 |
| 0.9.3-dev.53 | 176 | 2/17/2023 |
| 0.9.3-dev.52 | 191 | 2/17/2023 |
| 0.9.3-dev.44 | 217 | 1/24/2023 |
| 0.9.3-dev.43 | 208 | 1/23/2023 |
| 0.9.3-dev.42 | 198 | 1/23/2023 |
| 0.9.3-dev.41 | 213 | 1/23/2023 |
| 0.9.3-dev.40 | 206 | 1/19/2023 |
| 0.9.3-dev.34 | 201 | 12/30/2022 |
| 0.9.3-dev.33 | 188 | 12/30/2022 |
| 0.9.3-dev.30 | 234 | 11/29/2022 |
| 0.9.3-dev.29 | 198 | 11/18/2022 |
| 0.9.3-dev.19 | 213 | 11/11/2022 |
| 0.9.3-dev.17 | 198 | 11/10/2022 |
| 0.9.2 | 623 | 10/24/2022 |
| 0.9.1 | 632 | 10/23/2022 |
| 0.9.0 | 671 | 10/20/2022 |
| 0.1.0 | 655 | 10/20/2022 |