summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/Events
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-08-09 11:56:40 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-08-09 11:56:40 -0400
commit066f1857a145c8b9e80a095d2dee1be6419f957b (patch)
tree2ebfc4533fa204e1264286067a419f17aa981de7 /src/SMAPI/Framework/Events
parentc03430ec7eba11462664a043f14e2f2a122674a1 (diff)
downloadSMAPI-066f1857a145c8b9e80a095d2dee1be6419f957b.tar.gz
SMAPI-066f1857a145c8b9e80a095d2dee1be6419f957b.tar.bz2
SMAPI-066f1857a145c8b9e80a095d2dee1be6419f957b.zip
fix error when mods add/remove events asynchronously
Diffstat (limited to 'src/SMAPI/Framework/Events')
-rw-r--r--src/SMAPI/Framework/Events/ManagedEvent.cs43
1 files changed, 26 insertions, 17 deletions
diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs
index 8b25a9b5..f2dfb2ab 100644
--- a/src/SMAPI/Framework/Events/ManagedEvent.cs
+++ b/src/SMAPI/Framework/Events/ManagedEvent.cs
@@ -70,27 +70,33 @@ namespace StardewModdingAPI.Framework.Events
/// <param name="mod">The mod which added the event handler.</param>
public void Add(EventHandler<TEventArgs> handler, IModMetadata mod)
{
- EventPriority priority = handler.Method.GetCustomAttribute<EventPriorityAttribute>()?.Priority ?? EventPriority.Normal;
- var managedHandler = new ManagedEventHandler<TEventArgs>(handler, this.RegistrationIndex++, priority, mod);
+ lock (this.Handlers)
+ {
+ EventPriority priority = handler.Method.GetCustomAttribute<EventPriorityAttribute>()?.Priority ?? EventPriority.Normal;
+ var managedHandler = new ManagedEventHandler<TEventArgs>(handler, this.RegistrationIndex++, priority, mod);
- this.Handlers.Add(managedHandler);
- this.CachedHandlers = null;
- this.HasNewHandlers = true;
+ this.Handlers.Add(managedHandler);
+ this.CachedHandlers = null;
+ this.HasNewHandlers = true;
+ }
}
/// <summary>Remove an event handler.</summary>
/// <param name="handler">The event handler.</param>
public void Remove(EventHandler<TEventArgs> handler)
{
- // match C# events: if a handler is listed multiple times, remove the last one added
- for (int i = this.Handlers.Count - 1; i >= 0; i--)
+ lock (this.Handlers)
{
- if (this.Handlers[i].Handler != handler)
- continue;
+ // match C# events: if a handler is listed multiple times, remove the last one added
+ for (int i = this.Handlers.Count - 1; i >= 0; i--)
+ {
+ if (this.Handlers[i].Handler != handler)
+ continue;
- this.Handlers.RemoveAt(i);
- this.CachedHandlers = null;
- break;
+ this.Handlers.RemoveAt(i);
+ this.CachedHandlers = null;
+ break;
+ }
}
}
@@ -106,14 +112,17 @@ namespace StardewModdingAPI.Framework.Events
// update cached data
// (This is debounced here to avoid repeatedly sorting when handlers are added/removed,
// and keeping a separate cached list allows changes during enumeration.)
- var handlers = this.CachedHandlers; // iterate local copy in case a mod adds/removes a handler while handling the event
+ var handlers = this.CachedHandlers; // iterate local copy in case a mod adds/removes a handler while handling the event, which will set this field to null
if (handlers == null)
{
- if (this.HasNewHandlers && this.Handlers.Any(p => p.Priority != EventPriority.Normal))
- this.Handlers.Sort();
+ lock (this.Handlers)
+ {
+ if (this.HasNewHandlers && this.Handlers.Any(p => p.Priority != EventPriority.Normal))
+ this.Handlers.Sort();
- this.CachedHandlers = handlers = this.Handlers.ToArray();
- this.HasNewHandlers = false;
+ this.CachedHandlers = handlers = this.Handlers.ToArray();
+ this.HasNewHandlers = false;
+ }
}
// raise event