Files
ADP/TestingModule/ViewModels/LogAreaViewModel.cs
2026-06-25 17:00:17 +08:00

120 lines
3.8 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 UIShare.GlobalVariable;
using Logger;
using Prism.Ioc;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using UIShare.ViewModelBase;
namespace TestingModule.ViewModels
{
public class LogAreaViewModel : NavigateViewModelBase, IDisposable
{
// 日志集合
private ObservableCollection<LogItem> _logs = new();
public ObservableCollection<LogItem> Logs
{
get => _logs;
set => SetProperty(ref _logs, value);
}
public ICommand ClearLogCommand { get; set; }
private readonly ScopedContext _scopedContext;
private readonly GlobalInfo _globalInfo;
/// <summary>UI 线程定时器,每 100ms 批量从 LogBuffer 出队并刷新</summary>
private readonly DispatcherTimer _flushTimer;
public LogAreaViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
ClearLogCommand = new DelegateCommand(ClearLog);
_scopedContext = containerProvider.Resolve<ScopedContext>();
_globalInfo = containerProvider.Resolve<GlobalInfo>();
// UI 线程定时器:每 100ms 从 ScopedContext.LogBuffer 批量出队并 Add
_flushTimer = new DispatcherTimer(DispatcherPriority.Normal, System.Windows.Application.Current.Dispatcher)
{
Interval = TimeSpan.FromMilliseconds(100)
};
_flushTimer.Tick += FlushLogBuffer;
_flushTimer.Start();
}
/// <summary>
/// 定时批量刷新日志:一次性出队并 AddWPF 对连续 Add 做合并渲染
/// </summary>
private void FlushLogBuffer(object? sender, EventArgs e)
{
if (_scopedContext.LogBuffer.IsEmpty || Logs == null) return;
var batch = new List<(string Message, Brush Color, int Depth)>();
while (_scopedContext.LogBuffer.TryDequeue(out var item))
{
batch.Add(item);
}
// 批量 AddWPF 会对连续 Add 做合并渲染,只触发一次 layout/render pass
foreach (var item in batch)
{
Logs.Add(new LogItem(item.Message, item.Color, item.Depth));
}
}
private void ClearLog()
{
// 清空缓冲区,防止定时器下次还把旧数据刷出来
while (_scopedContext.LogBuffer.TryDequeue(out _)) { }
Logs?.Clear();
}
/// <summary>
/// 完善后的资源释放方法
/// </summary>
public void Dispose()
{
try
{
// 停止定时器
_flushTimer.Stop();
_flushTimer.Tick -= FlushLogBuffer;
// 最后一次刷新缓冲区中的剩余日志
FlushLogBuffer(null, EventArgs.Empty);
if (Logs != null)
{
Logs.Clear();
Logs = null!;
}
}
catch (Exception ex)
{
Logger.LoggerHelper.ErrorWithNotify(
_scopedContext != null ? _globalInfo.CurrentScope : "",
$"释放日志组件LogAreaViewModel资源失败: {ex.Message}");
}
}
}
// 日志条目类
public class LogItem
{
public string Message { get; set; }
public Brush Color { get; set; } = Brushes.Black;
public int Depth { get; set; }
public LogItem(string message, Brush color, int depth = 0)
{
Message = new string(' ', depth * 20) + message;
Color = color;
Depth = depth;
}
}
}