Visual Studio | WPF > Taskクラス + await async > Startボタン、Cancelボタンでのタスクの開始とキャンセル処理 v0.3

```txt:動作環境
Windows 8.1 Pro (64bit)
Microsoft Visual Studio 2017 Community
Sublime Text 2
```

関連: [Visual Studio | WPF > 非同期処理 > Link: ざっくりマルチスレッド(非同期処理)](https://qiita.com/7of9/items/5f9d900f01d6e6afc703)

[Visual Studio | WPF > Taskクラス > Startボタン, Cancelボタンでのタスクの開始、キャンセル処理 v0.1, v0.2](https://qiita.com/7of9/items/7b423908b8765e68b424)
ではTaskクラスを使って実装した。

これにawaitとasyncを加える。

### 参考

- [WPFメモ　非同期キャンセル処理 画面サンプル](https://qiita.com/Kosen-amai/items/20868649f10b119ceb40) by @Kosen-amai さん
- [async/awaitについての備忘録](https://qiita.com/mounntainn/items/3f39e0c57412c48508bf) by @mounntainn さん
- [できる！C#で非同期処理(Taskとasync-await)](https://www.kekyo.net/2016/12/06/6186) by KOUJI MATSUI (KEKYO)さん

### code v0.3

```MainWindow.xaml
<Window x:Class="_171220_t1320_taskCancel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:_171220_t1320_taskCancel"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Button Name="B_start" Content="Start" Height="30"
                Click="B_start_Click"/>
            <Button Name="B_cancel" Content="Cancel" Height="30"
                Click="B_cancel_Click"/>
        </StackPanel>
    </Grid>
</Window>
```

```MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
// 以下を追加した
using System.Threading;

namespace _171220_t1320_taskCancel
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private CancellationTokenSource cts = null;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void B_start_Click(object sender, RoutedEventArgs e)
        {
            Task tsk = Task.Run(() => WaitTaskAsync());
        }

        private async void WaitTaskAsync()
        {
            cts = new CancellationTokenSource();

            Console.WriteLine("Task wait");
            await SubTaskAsync(cts);

            cts.Dispose();
            cts = null;
        }

        private async Task SubTaskAsync(CancellationTokenSource cts)
        {
            for(int loop=0; loop<10; loop++)
            {
                try
                {
                    await Task.Delay(1000, cts.Token); // msec
                }
                catch (OperationCanceledException exc)
                {
                    Console.WriteLine("Canceled: {0}", exc.Message);
                    return;
                }
            }
            Console.WriteLine("Task ended");
            return;
        }

        private void B_cancel_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }
    }
}
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/a74e9882-8a77-ddee-30c8-2a111296034e.png)

- B_start_Click()の処理は要改善かもしれない
- Startボタンを複数回押下できる点も要改善

### 追記

https://msdn.microsoft.com/ja-jp/library/hh191443(v=vs.120).aspx
のReturn Types and Parameters

> An async method can also be a Sub method (Visual Basic) or have a void return type (C#). This return type is used primarily to define event handlers, where a void return type is required. Async event handlers often serve as the starting point for async programs.

```csharp
        private void B_start_Click(object sender, RoutedEventArgs e)
        {
            Task tsk = Task.Run(() => WaitTaskAsync());
        }
```

の部分は以下でもCancelボタンを押せるようだ。

```csharp
        private void B_start_Click(object sender, RoutedEventArgs e)
        {
            WaitTaskAsync();
        }
```

**注意: このあたりはまだ理解が浅い**

上記のリンク先のページ最下部のStartButton_Click()では、async void宣言をして、awaitを使ってAccessTheWebAsync()をコールしている。