SSPC-Tester/SSPCTester.UI/Services/UserSettingsStore.cs
2026-06-30 12:10:29 +08:00

97 lines
3.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.IO;
using System.Text.Json;
using Microsoft.Extensions.Options;
using SSPCTester.Devices.Config;
namespace SSPCTester.UI.Services;
/// <summary>将机器本地硬件配置保存到 LocalAppData不修改发布目录。</summary>
public sealed class UserSettingsStore : IDisposable
{
private static readonly JsonSerializerOptions JsonOptions = new()
{
WriteIndented = true,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
private readonly DeviceOptions _devices;
private readonly StorageOptions _storage;
private readonly ReportOptions _report;
private readonly SemaphoreSlim _writeLock = new(1, 1);
private readonly object _timerLock = new();
private Timer? _timer;
public UserSettingsStore(
IOptions<DeviceOptions> devices,
IOptions<StorageOptions> storage,
IOptions<ReportOptions> report)
{
_devices = devices.Value;
_storage = storage.Value;
_report = report.Value;
}
public static string SettingsPath => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"SSPCTester", "settings.json");
public void ScheduleSave()
{
lock (_timerLock)
{
_timer?.Dispose();
_timer = new Timer(async _ =>
{
try { await SaveAsync().ConfigureAwait(false); }
catch { /* 后续显式保存或退出时会再次尝试 */ }
}, null, 600, Timeout.Infinite);
}
}
public async Task SaveAsync()
{
await _writeLock.WaitAsync().ConfigureAwait(false);
try
{
string path = SettingsPath;
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
string temp = path + ".tmp";
_devices.Daq.Channels = DaqChannelOptionsNormalizer.Normalize(_devices.Daq.Channels);
var model = new
{
Devices = _devices,
Storage = _storage,
Report = _report
};
await File.WriteAllTextAsync(temp, JsonSerializer.Serialize(model, JsonOptions)).ConfigureAwait(false);
File.Move(temp, path, true);
WriteDaqSaveTrace(path);
}
finally { _writeLock.Release(); }
}
private void WriteDaqSaveTrace(string settingsPath)
{
try
{
string logDir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"SSPCTester", "Logs");
Directory.CreateDirectory(logDir);
string channels = string.Join(", ", _devices.Daq.Channels
.OrderBy(x => x.PhysicalChannel)
.Select(x => $"CH{x.PhysicalChannel}:{x.Role}/{x.IsCalibrated}"));
File.AppendAllText(
Path.Combine(logDir, "settings-save.log"),
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} {settingsPath} Pre={_devices.Daq.PreTriggerMs:R} Post={_devices.Daq.PostTriggerMs:R} Channels=[{channels}]{Environment.NewLine}");
}
catch { }
}
public void Dispose()
{
lock (_timerLock) { _timer?.Dispose(); }
_writeLock.Dispose();
}
}