ただ非同期処理をするだけではなく、進捗状況をProgressBarで表示し、CancelボタンでCancelできるようにしています。
まずはXAMLです。Grid内だけ記載しています。
ViewModelです。
非同期処理を行う関数はTaskFuncなのですが、CancellationTokenを引数に取っているので、Cancelすると例外を出します。
進捗状況はProgressPercentに直接値を代入してXAMLのほうでProgressBarにBindingしています。
Windows FormではIProgressクラスを使用して値をUIスレッドに渡さないといけないのですが、
そもそもWPFではBindingによってUIスレッドとは切り離されているので、ただBindingするだけでいいと思います。
using System.Windows; using System.Threading; using System.Threading.Tasks; namespace AsyncAwaiteSample.ViewModels { public class MainWindowViewModel : ViewModel { CancellationTokenSource cancelSrc; public void Initialize() { } #region ProgressPercent変更通知プロパティ private int _ProgressPercent; public int ProgressPercent { get { return _ProgressPercent; } set { if (_ProgressPercent == value) return; _ProgressPercent = value; RaisePropertyChanged(); } } #endregion #region StartCommand private ViewModelCommand _StartCommand; public ViewModelCommand StartCommand { get { if (_StartCommand == null) { _StartCommand = new ViewModelCommand(Start); } return _StartCommand; } } public async void Start() { cancelSrc = new CancellationTokenSource(); await Task.Run(() => TaskFunc(cancelSrc.Token)); } #endregion #region StopCommand private ViewModelCommand _StopCommand; public ViewModelCommand StopCommand { get { if (_StopCommand == null) { _StopCommand = new ViewModelCommand(Stop); } return _StopCommand; } } public void Stop() { cancelSrc.Cancel(); } #endregion private void TaskFunc(CancellationToken cancel) { try { //時間がかかる処理 for (int i = 0; i < 100; i++) { Thread.Sleep(100); cancel.ThrowIfCancellationRequested(); ProgressPercent = i; } MessageBox.Show("Finish!!"); } catch (OperationCanceledException ex) { MessageBox.Show("Cancelされました", "エラー", MessageBoxButton.OK, MessageBoxImage.Error); } } } }
0 件のコメント:
コメントを投稿