diff --git a/src/Workspaces/Core/Portable/Options/GlobalOptionService.cs b/src/Workspaces/Core/Portable/Options/GlobalOptionService.cs index e98231d1840ad0d8706258fa5dd70d13959f428b..20264e0b1fdf18b86a8e44e55331fc6df6de5747 100644 --- a/src/Workspaces/Core/Portable/Options/GlobalOptionService.cs +++ b/src/Workspaces/Core/Portable/Options/GlobalOptionService.cs @@ -143,6 +143,17 @@ public void RefreshOption(OptionKey optionKey, object newValue) { lock (_gate) { + object oldValue; + + if (_currentValues.TryGetValue(optionKey, out oldValue)) + { + if (object.Equals(oldValue, newValue)) + { + // Value is still the same, no reason to raise events + return; + } + } + _currentValues = _currentValues.SetItem(optionKey, newValue); } diff --git a/src/Workspaces/Core/Portable/Options/OptionServiceFactory.cs b/src/Workspaces/Core/Portable/Options/OptionServiceFactory.cs index f195f5bc52e9656563dfbf63080e718d88298cf3..eb2ddb22d886a8817a31b9927f0e464939944847 100644 --- a/src/Workspaces/Core/Portable/Options/OptionServiceFactory.cs +++ b/src/Workspaces/Core/Portable/Options/OptionServiceFactory.cs @@ -65,17 +65,16 @@ public void OnWorkspaceDisposed(Workspace workspace) private void OnGlobalOptionServiceOptionChanged(object sender, OptionChangedEventArgs e) { - var eventHandlers = GetEventHandlers(); - if (eventHandlers.Length > 0) + _taskQueue?.ScheduleTask(() => { - _taskQueue?.ScheduleTask(() => + // Ensure we grab the event handlers inside the scheduled task to prevent a race of people unsubscribing + // but getting the event later on the UI thread + var eventHandlers = GetEventHandlers(); + foreach (var handler in eventHandlers) { - foreach (var handler in eventHandlers) - { - handler(this, e); - } - }, "OptionsService.SetOptions"); - } + handler(this, e); + } + }, "OptionsService.SetOptions"); } private ImmutableArray> GetEventHandlers() @@ -98,7 +97,7 @@ private ImmutableArray> GetEventHandlers() remove { - lock(_gate) + lock (_gate) { _eventHandlers = _eventHandlers.Remove(value); }