using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using NLog; using SpineViewer.Resources; using SpineViewer.Services; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SpineViewer.ViewModels { public partial class ProgressDialogViewModel : ObservableObject, IProgressReporter, IDisposable { private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); private readonly CancellationTokenSource _cts = new(); private readonly Task _task; public ProgressDialogViewModel(Action work) { _task = new(() => { try { work(this, _cts.Token); WorkFinished?.Invoke(this, true); } catch (OperationCanceledException) { _logger.Info("Work cancelled by user: {0}", _title); WorkFinished?.Invoke(this, false); } catch (Exception ex) { _logger.Trace(ex.ToString()); _logger.Error("Failed to finish work: {0}, {1}", _title, ex.Message); WorkFinished?.Invoke(this, false); } }); } public void Start() => _task.Start(); public event EventHandler? WorkFinished; [ObservableProperty] private string _title = "Progress"; [ObservableProperty] private float _total = 100; [ObservableProperty] private float _done = 0; [ObservableProperty] private string _progressText = "Working..."; public RelayCommand Cmd_Cancel => _cmd_Cancel ??= new(Cancel_Execute, Cancel_CanExecute); private RelayCommand? _cmd_Cancel; private void Cancel_Execute() { if (!Cancel_CanExecute()) return; if (!MessagePopupService.OKCancel(AppResource.Str_CancelQuest)) return; _cts.Cancel(); Cmd_Cancel.NotifyCanExecuteChanged(); } private bool Cancel_CanExecute() => !_cts.IsCancellationRequested; #region IDisposable 接口实现 private bool _disposed = false; protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { _cts.Dispose(); _task.Dispose(); } _disposed = true; } ~ProgressDialogViewModel() { Dispose(false); } public void Dispose() { Dispose(true); if (_disposed) { GC.SuppressFinalize(this); } } #endregion } }