Files
CapMachine/CapMachine.Wpf/Models/MonitorValueLog.cs

144 lines
5.7 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 CapMachine.Wpf.Services;
using System;
using System.Threading;
namespace CapMachine.Wpf.Models
{
/// <summary>
/// 监控值日志
/// 负责监控5个整型值的变化。通过5个独立的更新方法实时赋值建议调用周期≈500ms
/// 当值发生变化时,记录“旧值 -> 新值”到日志,仅在变化时记录以保证效率。
/// 线程安全:采用 Interlocked/Volatile 保证无锁原子更新,避免不必要的锁竞争。
/// </summary>
public class MonitorValueLog
{
/// <summary>
/// 日志服务
/// </summary>
public ILogService LogService { get; }
private readonly string _name1;
private readonly string _name2;
private readonly string _name3;
private readonly string _name4;
private readonly string _name5;
private volatile int _value1;
private volatile int _value2;
private volatile int _value3;
private volatile int _value4;
private volatile int _value5;
// 0=未初始化1=已初始化使用int以便Interlocked操作
private int _v1Initialized;
private int _v2Initialized;
private int _v3Initialized;
private int _v4Initialized;
private int _v5Initialized;
private readonly string _context;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="logService">日志服务</param>
public MonitorValueLog(ILogService logService) : this(logService, "Value1", "Value2", "Value3", "Value4", "Value5", null)
{ }
/// <summary>
/// 构造函数支持为5个值自定义名称和上下文标识
/// </summary>
/// <param name="logService">日志服务</param>
/// <param name="name1">值1名称</param>
/// <param name="name2">值2名称</param>
/// <param name="name3">值3名称</param>
/// <param name="name4">值4名称</param>
/// <param name="name5">值5名称</param>
/// <param name="context">上下文/标签(可选),用于区分不同监控源</param>
public MonitorValueLog(ILogService logService, string name1, string name2, string name3, string name4, string name5, string context = null)
{
LogService = logService ?? throw new ArgumentNullException(nameof(logService));
_name1 = string.IsNullOrWhiteSpace(name1) ? "Value1" : name1;
_name2 = string.IsNullOrWhiteSpace(name2) ? "Value2" : name2;
_name3 = string.IsNullOrWhiteSpace(name3) ? "Value3" : name3;
_name4 = string.IsNullOrWhiteSpace(name4) ? "Value4" : name4;
_name5 = string.IsNullOrWhiteSpace(name5) ? "Value5" : name5;
_context = string.IsNullOrWhiteSpace(context) ? string.Empty : $"[{context}] ";
}
/// <summary>
/// 当前值的只读访问器(可选)
/// </summary>
public int Value1 => Volatile.Read(ref _value1);
public int Value2 => Volatile.Read(ref _value2);
public int Value3 => Volatile.Read(ref _value3);
public int Value4 => Volatile.Read(ref _value4);
public int Value5 => Volatile.Read(ref _value5);
/// <summary>
/// 更新第1个值仅在变化时记录旧值 -> 新值)
/// </summary>
/// <param name="newValue">新值</param>
public void UpdateValue1(int newValue) => Update(ref _value1, ref _v1Initialized, _name1, newValue);
/// <summary>
/// 更新第2个值仅在变化时记录旧值 -> 新值)
/// </summary>
/// <param name="newValue">新值</param>
public void UpdateValue2(int newValue) => Update(ref _value2, ref _v2Initialized, _name2, newValue);
/// <summary>
/// 更新第3个值仅在变化时记录旧值 -> 新值)
/// </summary>
/// <param name="newValue">新值</param>
public void UpdateValue3(int newValue) => Update(ref _value3, ref _v3Initialized, _name3, newValue);
/// <summary>
/// 更新第4个值仅在变化时记录旧值 -> 新值)
/// </summary>
/// <param name="newValue">新值</param>
public void UpdateValue4(int newValue) => Update(ref _value4, ref _v4Initialized, _name4, newValue);
/// <summary>
/// 更新第5个值仅在变化时记录旧值 -> 新值)
/// </summary>
/// <param name="newValue">新值</param>
public void UpdateValue5(int newValue) => Update(ref _value5, ref _v5Initialized, _name5, newValue);
/// <summary>
/// 内部更新逻辑:原子更新与变化日志
/// </summary>
private void Update(ref int target, ref int initializedFlag, string name, int newValue)
{
// 首次赋值:仅建立基线,不记录日志
if (Interlocked.CompareExchange(ref initializedFlag, 1, 0) == 0)
{
Volatile.Write(ref target, newValue);
return;
}
// 原子交换拿到旧值
int oldValue = Interlocked.Exchange(ref target, newValue);
if (oldValue != newValue)
{
LogChange(name, oldValue, newValue);
}
}
/// <summary>
/// 记录变化日志(防御性:日志失败不影响主流程)
/// </summary>
private void LogChange(string name, int oldValue, int newValue)
{
try
{
LogService.Info($"{_context}[MonitorValueLog] {name} 变化: {oldValue} -> {newValue}");
}
catch
{
// 忽略日志异常,保证主流程稳定
}
}
}
}