2016/10/30

WPF(Livet)でasync/awaitを使って非同期処理

async/awaitを使って非同期処理を行うサンプルを載せます。
ただ非同期処理をするだけではなく、進捗状況を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 件のコメント:

コメントを投稿