Explorar el Código

为 Config 添加延迟写入

龙腾猫跃 hace 3 meses
padre
commit
fc92759a39
Se han modificado 2 ficheros con 51 adiciones y 17 borrados
  1. 46 16
      Shared/General/Config.cs
  2. 5 1
      Shared/MeloongCore.csproj

+ 46 - 16
Shared/General/Config.cs

@@ -23,7 +23,9 @@ public class JsonConfigProvider : IConfigProvider {
     private readonly string filePath;
     public JsonConfigProvider(string filePath) {
         this.filePath = filePath;
+        saveAction = Throttler.Throttle(SaveImmediately, TimeSpan.FromMilliseconds(500), leading: false, trailing: true);
         InitJson();
+        AppDomain.CurrentDomain.ProcessExit += (_, _) => SaveBeforeExit();
     }
 
     // 原始文件缓存
@@ -41,22 +43,30 @@ public class JsonConfigProvider : IConfigProvider {
         });
     }
 
+    // ================================= 设置、读取、缓存 =================================
+
     public void SetToCache<T>(string key, T? value, bool encrypted) {
         cache[key] = value;
-        if (value is null) {
-            // 直接在 JSON 中表示为 null
-            json.Value[key] = JValue.CreateNull();
-        } else if (encrypted) {
-            // 需要加密,在 JSON 中保存密文字符串
-            json.Value[key] = CryptographyUtils.AesEncrypt(value is string str ? str : JsonConvert.SerializeObject(value)); // TODO: 加密改为使用识别码
-        } else {
-            // 用 JToken 保留原始结构
-            json.Value[key] = JToken.FromObject(value);
+        lock (json) {
+            if (value is null) {
+                // 直接在 JSON 中表示为 null
+                json.Value[key] = JValue.CreateNull();
+            } else if (encrypted) {
+                // 需要加密,在 JSON 中保存密文字符串
+                json.Value[key] = CryptographyUtils.AesEncrypt(value is string str ? str : JsonConvert.SerializeObject(value)); // TODO: 加密改为使用识别码
+            } else {
+                // 用 JToken 保留原始结构
+                json.Value[key] = JToken.FromObject(value);
+            }
         }
     }
     public T? Read<T>(string key, T? defaultValue, bool encrypted) {
         if (cache.TryGetValue(key, out var cachedValue)) return (T?) cachedValue; // 读取缓存
-        if (!json.Value.TryGetValue(key, out var entry)) return defaultValue; // 未找到该键
+        JToken entry;
+        lock (json) {
+            if (!json.Value.TryGetValue(key, out entry!)) return defaultValue; // 未找到该键
+            entry = entry.DeepClone();
+        }
         try {
             T? result;
             if (entry.Type is JTokenType.Null or JTokenType.Undefined) {
@@ -77,18 +87,38 @@ public class JsonConfigProvider : IConfigProvider {
         }
     }
 
-    public bool HasValue(string key)
-        => json.Value.ContainsKey(key);
+    public bool HasValue(string key) {
+        lock (json) return json.Value.ContainsKey(key);
+    }
     public void RemoveFromCache(string key) {
-        json.Value.Remove(key);
+        lock (json) json.Value.Remove(key);
         cache.TryRemove(key, out _);
     }
     public void DiscardCache() {
-        InitJson();
+        lock (json) InitJson();
         cache.Clear();
     }
-    public void Save()
-        => FileUtils.Write(filePath, json.Value.ToString(Formatting.Indented));
+
+    // ===================================== 保存 =====================================
+
+    private readonly RateLimitedAction saveAction;
+    private bool isDirty = false;
+    public void Save() {
+        lock (json) isDirty = true;
+        saveAction.Invoke();
+    }
+    private void SaveBeforeExit() {
+        bool shouldSave;
+        lock (json) shouldSave = isDirty;
+        if (shouldSave) SaveImmediately();
+        saveAction.Dispose();
+    }
+    private void SaveImmediately() {
+        lock (json) {
+            FileUtils.Write(filePath, json.Value.ToString(Formatting.Indented));
+            isDirty = false;
+        }
+    }
 }
 
 public static class ConfigUtils {

+ 5 - 1
Shared/MeloongCore.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
 	<PropertyGroup>
 		<TargetFramework>netstandard2.0</TargetFramework>
@@ -22,6 +22,7 @@
 	</ItemGroup>
 
 	<ItemGroup>
+		<Using Include="ThrottleDebounce" />
 		<Using Include="System.Diagnostics.CodeAnalysis" />
 		<Using Include="System.Collections" />
 		<Using Include="System.Collections.Generic" />
@@ -36,6 +37,9 @@
 	</ItemGroup>
 
 	<ItemGroup>
+		<Reference Include="ThrottleDebounce">
+			<HintPath>..\..\Plain Craft Launcher 2\Resources\ThrottleDebounce.dll</HintPath>
+		</Reference>
 		<Reference Include="Newtonsoft.Json">
 			<HintPath>..\..\Plain Craft Launcher 2\Resources\Newtonsoft.Json.dll</HintPath>
 		</Reference>