Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Visual Studio | WPF > Taskクラス > Startボタン, Cancelボタンでのタスクの開始、キャンセル処理 v0.1, v0.2

More than 3 years have passed since last update.
動作環境
Windows 8.1 Pro (64bit)
Microsoft Visual Studio 2017 Community
Sublime Text 2

関連: Visual Studio | WPF > 非同期処理 > Link: ざっくりマルチスレッド(非同期処理)

処理概要

  • Startボタン: Taskを開始
  • Cancelボタン: Taskをキャンセル
  • Start後に設定時間経過後にTaskが終了
  • Taskクラスを用いた実装

参考

Task クラス
Task.Wait メソッド (CancellationToken)

code v0.1

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 bool bfStop = false;

        public MainWindow()
        {
            InitializeComponent();
        }

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

        private void WaitTask()
        {
            using (var cts = new CancellationTokenSource())
            {
                Task tsk = Task.Run(() => SubTask(cts));

                try
                {
                    Console.WriteLine("Task wait");
                    tsk.Wait(cts.Token);
                }
                catch (OperationCanceledException exc)
                {
                    Console.WriteLine("Canceled: {0}", exc.Message);
                }
            }
        }

        private void SubTask(CancellationTokenSource cts)
        {
            for(int loop=0; loop<10; loop++)
            {
                Task.Delay(1000).Wait(); // msec
                if (bfStop)
                {
                    cts.Cancel();
                    return;
                }
            }
            Console.WriteLine("Task ended");
        }

        private void B_cancel_Click(object sender, RoutedEventArgs e)
        {
            bfStop = true;
        }
    }
}

実行例

  • Startボタン押下, Cancelボタン押下
  • Startボタン押下, Cancelボタン押下
  • Startボタン押下, 放置

qiita.png

備考

  • B_start_Click()内でtsk.Wait()するとCancelボタンが使用できない
    • 処理を抜けていないから
  • 上記の実装が「標準的か」はもっといろいろ実装してからでないと分からない
    • async, awaitはそのうち勉強する
    • Task tskの宣言位置は変更した方がいいかもしれない
  • usingステートメントにはtry, catchをした方がいいかもしれない: 関連

code v0.2

async/awaitについての備忘録 by @mounntainn さん
を参考にB_cancel_Clickの処理を変更してみた。

  • bfStop廃止
  • B_cancel_Click()にてcts.Cancel()実行
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;

        public MainWindow()
        {
            InitializeComponent();
        }

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

        private void WaitTask()
        {
            cts = new CancellationTokenSource();

            Task tsk = Task.Run(() => SubTask(cts));

            try
            {
                Console.WriteLine("Task wait");
                tsk.Wait(cts.Token);
            }
            catch (OperationCanceledException exc)
            {
                Console.WriteLine("Canceled: {0}", exc.Message);
            }

            cts.Dispose();
        }

        private void SubTask(CancellationTokenSource cts)
        {
            for(int loop=0; loop<10; loop++)
            {
                Task.Delay(1000).Wait(); // msec
                if (cts.IsCancellationRequested)
                {
                    return;
                }
            }
            Console.WriteLine("Task ended");
        }

        private void B_cancel_Click(object sender, RoutedEventArgs e)
        {
            cts.Cancel();
        }
    }
}

v0.1と比べてCancel処理が早くなったようだ。

WPFメモ 非同期キャンセル処理 画面サンプル by @Kosen-amai さんの記事にもフラグ処理とトークン処理の違いが紹介されている。

#region 左側の処理(キャンセル押してから終了するまでにタイムラグあり)

7of9
セブンオブナインです。Unimatrix 01の第三付属物 9の7という識別番号です。Star trek Voyagerの好きなキャラクターです。まとめ記事は後日タイトルから内容がわからなくなるため、title検索で見つかるよう個々の記事にしてます。いわゆるBorg集合体の有名なセリフから「お前たち(の知識)を吸収する。抵抗は無意味だ」。Thanks in advance.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away