From a1d60415574b9d12953bd45163aea3b177467557 Mon Sep 17 00:00:00 2001 From: Peter Morris Date: Fri, 9 Dec 2022 12:52:21 +0000 Subject: [PATCH] Fix memory leak when using ActionSubscriber or SubscribeToAction (Fixes #378) (#380) Fix memory leak when using ActionSubscriber or SubscribeToAction (Fixes #378) --- Docs/releases.md | 3 +++ Source/Lib/Fluxor/ActionSubscriber.cs | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Docs/releases.md b/Docs/releases.md index 0e96380c..c419d281 100644 --- a/Docs/releases.md +++ b/Docs/releases.md @@ -1,5 +1,8 @@ # Releases +## New in 5.7 +* Fixes memory leak when using `ActionSubscriber` or `SubscribeToAction` ([#378](https://github.com/mrpmorris/Fluxor/issues/378)) + ## New in 5.6 * Support .NET 7 * Ensure StateSelection unsubscribes properly ([#353](https://github.com/mrpmorris/Fluxor/issues/353)) diff --git a/Source/Lib/Fluxor/ActionSubscriber.cs b/Source/Lib/Fluxor/ActionSubscriber.cs index ec4953af..4768e590 100644 --- a/Source/Lib/Fluxor/ActionSubscriber.cs +++ b/Source/Lib/Fluxor/ActionSubscriber.cs @@ -1,8 +1,6 @@ -using Fluxor.Extensions; using System; using System.Collections.Generic; using System.Linq; -using System.Threading; namespace Fluxor { @@ -23,7 +21,7 @@ public void Notify(object action) if (action is null) throw new ArgumentNullException(nameof(action)); - lock(SyncRoot) + lock (SyncRoot) { IEnumerable> callbacks = SubscriptionsForType @@ -48,7 +46,7 @@ public void SubscribeToAction(object subscriber, Action callba actionType: typeof(TAction), callback: (object action) => callback((TAction)action)); - lock(SyncRoot) + lock (SyncRoot) { if (!SubscriptionsForInstance.TryGetValue(subscriber, out List instanceSubscriptions)) { @@ -72,17 +70,22 @@ public void UnsubscribeFromAllActions(object subscriber) throw new ArgumentNullException(nameof(subscriber)); List instanceSubscriptions; - lock(SyncRoot) + lock (SyncRoot) { if (!SubscriptionsForInstance.TryGetValue(subscriber, out instanceSubscriptions)) return; + IEnumerable subscribedInstances = + instanceSubscriptions + .Select(x => x.Subscriber) + .Distinct(); + IEnumerable subscribedActionTypes = instanceSubscriptions .Select(x => x.ActionType) .Distinct(); - foreach(Type actionType in subscribedActionTypes) + foreach (Type actionType in subscribedActionTypes) { List actionTypeSubscriptions; if (!SubscriptionsForType.TryGetValue(actionType, out actionTypeSubscriptions)) @@ -91,6 +94,9 @@ public void UnsubscribeFromAllActions(object subscriber) .Except(instanceSubscriptions) .ToList(); } + + foreach (object subscription in subscribedInstances) + SubscriptionsForInstance.Remove(subscription); } } }