using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; namespace ShrlAlgo.Addin.Test { // 用于给外界调用的报告器 public class ProgressReporter { private readonly ProgressViewModel _viewModel; private DateTime _lastUpdate = DateTime.MinValue; public ProgressReporter(ProgressViewModel viewModel) { _viewModel = viewModel; } /// /// 更新进度 (自带节流控制,防止频繁更新导致UI卡顿) /// public void Report(int current, int total, string message = null) { // 限制 UI 刷新频率(每 50 毫秒最多刷新一次) if ((DateTime.Now - _lastUpdate).TotalMilliseconds < 50 && current != total) return; _lastUpdate = DateTime.Now; _viewModel.Update(current, total, message); } public void ReportMessage(string message) => _viewModel.UpdateMessage(message); } // WPF 的 ViewModel public class ProgressViewModel : INotifyPropertyChanged { private readonly CancellationTokenSource _cts; public Dispatcher UIDispatcher { get; set; } public Action CloseAction { get; set; } public ProgressViewModel(string title, CancellationTokenSource cts) { Title = title; _cts = cts; } private string _title; public string Title { get => _title; set => SetProperty(ref _title, value); } private string _message = "正在准备..."; public string Message { get => _message; set => SetProperty(ref _message, value); } private double _progressValue; public double ProgressValue { get => _progressValue; set => SetProperty(ref _progressValue, value); } private double _maximum = 100; public double Maximum { get => _maximum; set => SetProperty(ref _maximum, value); } public void Cancel() { if (!_cts.IsCancellationRequested) { Message = "正在取消任务,请稍候..."; _cts.Cancel(); } } // 跨线程更新 UI public void Update(int current, int total, string message) { UIDispatcher?.InvokeAsync(() => { ProgressValue = current; Maximum = total; if (!string.IsNullOrEmpty(message)) Message = message; }); } public void UpdateMessage(string message) { UIDispatcher?.InvokeAsync(() => Message = message); } public event PropertyChangedEventHandler PropertyChanged; protected void SetProperty(ref T field, T value, [CallerMemberName] string propertyName = null) { field = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }