Dreamine.MVVM.ViewModels 1.0.5
Dreamine.MVVM.ViewModels 프로젝트의 API와 구성 요소를 제공합니다.
로딩중...
검색중...
일치하는것 없음
AsyncRelayCommand.cs
이 파일의 문서화 페이지로 가기
1using System;
2using System.Diagnostics;
3using System.Threading;
4using System.Threading.Tasks;
5using System.Windows.Input;
6
8{
17 public sealed class AsyncRelayCommand : ICommand
18 {
27 private readonly Func<Task> _execute;
36 private readonly Func<bool>? _canExecute;
37 // Interlocked: 0 = idle, 1 = executing. Prevents concurrent entry without lock.
46 private int _isExecuting;
55 private volatile Exception? _lastException;
56
89 public AsyncRelayCommand(Func<Task> execute, Func<bool>? canExecute = null)
90 {
91 _execute = execute ?? throw new ArgumentNullException(nameof(execute));
92 _canExecute = canExecute;
93 }
94
103 public event EventHandler? CanExecuteChanged;
104
113 public event EventHandler<Exception>? ExecutionFailed;
114
123 public Exception? LastException => _lastException;
124
149 public bool CanExecute(object? parameter)
150 {
151 return Volatile.Read(ref _isExecuting) == 0 && (_canExecute?.Invoke() ?? true);
152 }
153
170 public async void Execute(object? parameter)
171 {
172 // Atomically claim execution slot; bail if already executing.
173 if (Interlocked.CompareExchange(ref _isExecuting, 1, 0) != 0)
174 {
175 return;
176 }
177
179 try
180 {
181 await _execute().ConfigureAwait(true);
182 }
183 catch (Exception ex)
184 {
185 _lastException = ex;
186
187 var handler = ExecutionFailed;
188 if (handler is not null)
189 {
190 handler.Invoke(this, ex);
191 }
192 else
193 {
194 // No subscriber — emit a diagnostic trace so the exception is visible
195 // in the Output window rather than silently disappearing.
196 Debug.WriteLine(
197 $"[AsyncRelayCommand] Unhandled exception (subscribe to ExecutionFailed to suppress this): {ex}");
198 }
199 }
200 finally
201 {
202 Interlocked.Exchange(ref _isExecuting, 0);
204 }
205 }
206
216 {
217 CanExecuteChanged?.Invoke(this, EventArgs.Empty);
218 }
219 }
220}
AsyncRelayCommand(Func< Task > execute, Func< bool >? canExecute=null)