ソースコード
ファイル名:MainWindow.xaml
<Window x:Class="TaskCancelSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Task Cancel Sample"
Width="300"
Height="200">
<StackPanel Margin="20">
<Button x:Name="StartButton"
Content="開始"
Click="Start_Click"
Margin="0,0,0,10"/>
<Button x:Name="CancelButton"
Content="キャンセル"
Click="Cancel_Click"
IsEnabled="False"
Margin="0,0,0,10"/>
<TextBlock x:Name="StatusText"
Text="Idle"/>
</StackPanel>
</Window>
ファイル名:MainWindow.xaml.cs
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace TaskCancelSample;
public partial class MainWindow : Window
{
// キャンセルトークンソースの宣言
private CancellationTokenSource? _cts;
public MainWindow()
{
InitializeComponent();
}
// 開始ボタンクリック
private async void Start_Click(object sender, RoutedEventArgs e)
{
StartButton.IsEnabled = false; // 開始ボタン ... 無効
CancelButton.IsEnabled = true; // キャンセルボタン ... 有効
StatusText.Text = "実行中...";
// キャンセルトークンのインスタンス生成
_cts = new CancellationTokenSource();
try
{
await Task.Run(() => HeavyWork(_cts.Token));
StatusText.Text = "完了";
}
catch (OperationCanceledException)
{
StatusText.Text = "キャンセル済み";
}
finally
{
StartButton.IsEnabled = true; // 開始ボタン ... 有効
CancelButton.IsEnabled = false; // キャンセルボタン ... 有効
// キャンセルトークンソースの解放
_cts.Dispose();
_cts = null;
}
}
// キャンセルボタンクリック
private void Cancel_Click(object sender, RoutedEventArgs e)
{
// キャンセル発行
_cts?.Cancel();
}
// 重たい処理。
private void HeavyWork(CancellationToken token)
{
for (int i = 0; i < 10; i++)
{
// キャンセルリクエストでOperationCanceledExceptionをthrow
token.ThrowIfCancellationRequested();
// CPUを使う重たい処理の代わり
Thread.Sleep(1000);
// UI更新は Dispatcher 経由
Dispatcher.Invoke(() =>
{
StatusText.Text = $"Step {i + 1}";
});
}
}
}
実行例
- 実行ボタンを押す。

- カウントアップされる。

- キャンセルボタンを押す。→キャンセルされる


コメント