Skip to content

Commit 5930e61

Browse files
authored
perf: 缓存 ConfigManager 反射属性元数据并添加线程安全保护 (#121)
1 parent 3896ece commit 5930e61

1 file changed

Lines changed: 70 additions & 52 deletions

File tree

src/ConfigManager.cs

Lines changed: 70 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using Microsoft.Win32;
2-
using System;
3-
using System.Collections.Generic;
4-
using System.Linq;
2+
using System.Collections.Concurrent;
3+
using System.Reflection;
54

65
namespace BASpark
76
{
@@ -96,6 +95,12 @@ public static class ConfigManager
9695

9796
private static List<FilterProfile> _profiles = new List<FilterProfile>();
9897

98+
// 缓存属性元数据,避免 Save() 每次都反射查找
99+
private static readonly ConcurrentDictionary<string, PropertyInfo?> _propertyCache = new();
100+
101+
// 保护并发 Save / _profiles 访问
102+
private static readonly object _syncLock = new();
103+
99104
public static void Load()
100105
{
101106
try
@@ -236,20 +241,29 @@ public static void GetAnimationSpeedsForOverlay(out double trailSpeed, out doubl
236241
}
237242
}
238243

239-
public static List<FilterProfile> GetProfiles() => _profiles;
244+
public static List<FilterProfile> GetProfiles()
245+
{
246+
lock (_syncLock) { return [.. _profiles]; }
247+
}
240248

241249
public static FilterProfile? GetActiveProfile()
242250
{
243-
return _profiles.FirstOrDefault(p => p.Id == ActiveProfileId) ?? _profiles.FirstOrDefault();
251+
lock (_syncLock)
252+
{
253+
return _profiles.FirstOrDefault(p => p.Id == ActiveProfileId) ?? _profiles.FirstOrDefault();
254+
}
244255
}
245256

246257
public static void SaveProfiles(List<FilterProfile> profiles, string activeId)
247258
{
248-
_profiles = profiles;
249-
ActiveProfileId = activeId;
250-
string json = System.Text.Json.JsonSerializer.Serialize(_profiles);
251-
Save("FilterProfiles", json);
252-
Save("ActiveProfileId", activeId);
259+
lock (_syncLock)
260+
{
261+
_profiles = profiles;
262+
ActiveProfileId = activeId;
263+
string json = System.Text.Json.JsonSerializer.Serialize(_profiles);
264+
Save("FilterProfiles", json);
265+
Save("ActiveProfileId", activeId);
266+
}
253267
}
254268

255269
/// 将选中的视觉表现项恢复默认值并写入注册表
@@ -303,8 +317,9 @@ public static void Save(string name, object value)
303317
{
304318
try
305319
{
306-
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(RegPath))
320+
lock (_syncLock)
307321
{
322+
using RegistryKey key = Registry.CurrentUser.CreateSubKey(RegPath);
308323
if (value is Enum enumValue)
309324
{
310325
key.SetValue(name, enumValue.ToString());
@@ -314,7 +329,7 @@ public static void Save(string name, object value)
314329
key.SetValue(name, value);
315330
}
316331

317-
var prop = typeof(ConfigManager).GetProperty(name);
332+
var prop = _propertyCache.GetOrAdd(name, n => typeof(ConfigManager).GetProperty(n));
318333
if (prop != null)
319334
{
320335
object propertyValue = value;
@@ -487,48 +502,51 @@ public static void ResetAndClear()
487502
{
488503
try
489504
{
490-
Registry.CurrentUser.DeleteSubKeyTree(RegPath, false);
491-
492-
string oldJson = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.json");
493-
if (System.IO.File.Exists(oldJson))
505+
lock (_syncLock)
494506
{
495-
System.IO.File.Delete(oldJson);
496-
}
507+
Registry.CurrentUser.DeleteSubKeyTree(RegPath, false);
497508

498-
ParticleColor = "45,175,255";
499-
IsEffectEnabled = true;
500-
AutoStart = false;
501-
AgreedToPrivacy = false;
502-
EnableTelemetry = false;
503-
TotalClicks = 0;
504-
LastNoticeContent = "";
505-
EnableAlwaysTrailEffect = false;
506-
StartSilent = false;
507-
RunAsAdmin = false;
508-
EffectScale = 1.5;
509-
EffectOpacity = 1.0;
510-
EffectSpeed = 1.0;
511-
UseLinkedAnimationSpeed = true;
512-
TrailAnimationSpeed = 1.0;
513-
ClickAnimationSpeed = 1.0;
514-
TrailRefreshRate = 40;
515-
EnableEnvironmentFilter = false;
516-
HideInFullscreen = true;
517-
ShowEffectOnDesktop = true;
518-
FilterProfiles = "";
519-
ActiveProfileId = "";
520-
_profiles.Clear();
521-
IsTouchscreenMode = false;
522-
ClickTriggerType = 0;
523-
EnableMiddleClickTrigger = false;
524-
ScreenshotCompatibilityMode = false;
525-
EnabledScreenIds = "";
526-
ScreenSelections = "";
527-
UiLanguage = "";
528-
NetworkRegion = NetworkRegionOption.Auto;
529-
SidebarBackgroundImagePath = "";
530-
TelemetryClientId = "";
531-
LastTelemetrySentUtc = "";
509+
string oldJson = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.json");
510+
if (System.IO.File.Exists(oldJson))
511+
{
512+
System.IO.File.Delete(oldJson);
513+
}
514+
515+
ParticleColor = "45,175,255";
516+
IsEffectEnabled = true;
517+
AutoStart = false;
518+
AgreedToPrivacy = false;
519+
EnableTelemetry = false;
520+
TotalClicks = 0;
521+
LastNoticeContent = "";
522+
EnableAlwaysTrailEffect = false;
523+
StartSilent = false;
524+
RunAsAdmin = false;
525+
EffectScale = 1.5;
526+
EffectOpacity = 1.0;
527+
EffectSpeed = 1.0;
528+
UseLinkedAnimationSpeed = true;
529+
TrailAnimationSpeed = 1.0;
530+
ClickAnimationSpeed = 1.0;
531+
TrailRefreshRate = 40;
532+
EnableEnvironmentFilter = false;
533+
HideInFullscreen = true;
534+
ShowEffectOnDesktop = true;
535+
FilterProfiles = "";
536+
ActiveProfileId = "";
537+
_profiles.Clear();
538+
IsTouchscreenMode = false;
539+
ClickTriggerType = 0;
540+
EnableMiddleClickTrigger = false;
541+
ScreenshotCompatibilityMode = false;
542+
EnabledScreenIds = "";
543+
ScreenSelections = "";
544+
UiLanguage = "";
545+
NetworkRegion = NetworkRegionOption.Auto;
546+
SidebarBackgroundImagePath = "";
547+
TelemetryClientId = "";
548+
LastTelemetrySentUtc = "";
549+
}
532550
}
533551
catch (Exception ex)
534552
{

0 commit comments

Comments
 (0)