C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

■96016 / 1階層)  Task起動先が、Task起動元の終了を検知する方法について
□投稿者/ WebSurfer (2125回)-(2020/10/16(Fri) 11:05:59)
No96002 (taro さん) に返信

No96003 に書きました、

非同期プログラミングのベスト プラクティス
https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming

に沿ったサンプルを以下に書いておきます。

上の記事に書いてあるように「すべて非同期にする」ようにし、「自分のツールを理解する」に書い
てあるように CancellationTokenSource/CancellationToken と IProgress<T>/Progress<T> を利用し
ます。

Form1 から初期化して表示する Form2 という形ではなくて、Form1 単独として button1_Click で 
RunProcTask を起動、button2_Click でキャンセルしています。

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsAsyncTest
{
    public partial class Form1 : Form
    {
        private CancellationTokenSource cts = null;

        public Form5()
        {
            InitializeComponent();
        }

        // 開始(質問のコードの Form2_Shown の代わり)
        private async void button1_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = "タスク起動";

            var p = new Progress<string>(ShowProgress);

            using (this.cts = new CancellationTokenSource())
            {
                CancellationToken token = this.cts.Token;
                try
                {
                    await RunProcTask(p, token);
                }
                catch (OperationCanceledException)
                {
                    // 必要なら何らかの処置
                }
            }
        }

        // キャンセル
        private void button2_Click(object sender, EventArgs e)
        {
            if (this.cts != null) cts.Cancel();
        }


        // 処理タスク
        // ポーリングによるキャンセルのリッスン
        //  IProgress<T>/Progress<T> で進捗をレポート
        private async Task RunProcTask(IProgress<string> progress, CancellationToken token)
        {
            int i = 0;
            while (true)
            {
                token.ThrowIfCancellationRequested();
                await Task.Delay(1000);
                progress.Report(i.ToString());
                i++;
            }
        }

        // 進捗を TextBox に表示するコールバック
        // UIスレッドで呼び出される
        private void ShowProgress(string log)
        {
            this.textBox1.Text = "ログ出力その " + log;
        }

    }
}

マネージド スレッドのキャンセル
https://docs.microsoft.com/ja-jp/dotnet/standard/threading/cancellation-in-managed-threads

に書いてある「ポーリングによるリッスン」を行っています。RunProcTask メソッドの中の

token.ThrowIfCancellationRequested();

がそれで、以下のコードと同じ結果になります。

if (token.IsCancellationRequested)   
    throw new OperationCanceledException(token);

編集キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Task起動先が、Task起動元の終了を検知する方法について /taro 返信無し
 
上記関連ツリー

Task起動先が、Task起動元の終了を検知する方法について / taro (20/10/15(Thu) 10:33) #96002
Re[1]: Task起動先が、Task起動元の終了を検知する方法について / WebSurfer (20/10/15(Thu) 10:51) #96003
Re[1]: Task起動先が、Task起動元の終了を検知する方法について / WebSurfer (20/10/15(Thu) 11:10) #96005
Re[1]: Task起動先が、Task起動元の終了を検知する方法について / kiku (20/10/15(Thu) 14:58) #96009
│└ Re[2]: Task起動先が、Task起動元の終了を検知する方法について / furu (20/10/15(Thu) 15:45) #96010
│  └ Re[3]: Task起動先が、Task起動元の終了を検知する方法について / kiku (20/10/15(Thu) 15:48) #96011
│    └ Re[4]: Task起動先が、Task起動元の終了を検知する方法について / furu (20/10/15(Thu) 16:03) #96012
Task起動先が、Task起動元の終了を検知する方法について / WebSurfer (20/10/16(Fri) 11:05) #96016 ←Now
Re[1]: Task起動先が、Task起動元の終了を検知する方法について / WebSurfer (20/10/21(Wed) 11:50) #96093
  └ Re[2]: Task起動先が、Task起動元の終了を検知する方法について / taro (20/10/23(Fri) 14:40) #96149 解決済み

上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信