Help us understand the problem. What is going on with this article?

非同期で複数処理を実行し、対話式で制御する

More than 3 years have passed since last update.

概要

開始と終了命令をコンソールからいつでも入力可能かつ、開始時には非同期で複数の処理を実行可能で、任意のタイミングでいつでも処理を停止できるようなプログラムを組んでみた

こんなイメージ
スクリーンショット 2015-04-29 20.08.13.png

非同期でタスクを実行

// ABCを非同期で同時実行
Task.Run(ActionA);
Task.Run(ActionB);
Task.Run(ActionC);

タスクを取り消す

タスクを取り消すにはMSのタスクとその子を取り消すにある通りCancellationTokenSourceを利用すると実装できるみたい。

// キャンセルトークンの取得
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;

// トークン付きで実行
Task.Run(()=>ActionA(token), token);

// 停止命令を送る
tokenSource.Cancel()

// ActionAに停止処理を追加
static void ActionA(CancellationToken token)
   {
      while(true){
         // メインロジック
         Thread.sleep(1000);

         // キャンセル時の処理
         if (token.IsCancellationRequested) {
              break;
         } 
      }
   } 

実際のコード

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncPractice
{
    class Program
    {
        static void Main(string[] args)
        {
            // Task停止用のトークン発行
            var cancelTokenSource = new CancellationTokenSource();
            CancellationToken cToken = cancelTokenSource.Token;

            while (true)
            {

                // 入力受付
                Console.Write("> ");
                string msg = Console.ReadLine();

                // 処理開始
                if (msg == "stat" || msg == "s")
                {
                    Console.WriteLine("Ascnc Practice START");

                    // 非同期処理をそれぞれ実行
                    Task.Run(() => sleep("processA", 3000, cToken), cToken);
                    Task.Run(() => sleep("processB", 5000, cToken), cToken);
                    Task.Run(() => sleep("processC", 1000, cToken), cToken);

                    continue;
                }

                // 処理終了
                if (msg == "stop")
                {
                    // 非同期処理の終了
                    cancelTokenSource.Cancel();
                    Console.WriteLine("Stop!");
                }

                // アプリ終了
                if (msg == "quit" || msg == "q")
                {
                    break;
                }

            }
            // 非同期処理の終了
            cancelTokenSource.Cancel();
            cancelTokenSource.Dispose();
        }

        public static void sleep(string tag, int millseconds, CancellationToken token)
        {
            int ct = 0;
            while (true)
            {
                Thread.Sleep(millseconds);
                ct += 1;
                Console.WriteLine("[{0}] {1}回目のループ完了", tag, ct.ToString());

                // 中止リクエストあれば停止
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("[{0}] 処理停止", tag);
                    break;
                }
            }
        }

    }
}


実行してみた

スクリーンショット 2015-04-29 20.31.46.png

スクリーンショット 2015-04-29 20.32.18.png

実現できていなこと

・中断と再開の処理が上記コードでは実現できていない。
・CancellationTokenSourceは使い捨て推奨だが、このコードでは使い回している。disposeした後にtokenを再利用すると破棄されているためエラーが発生する。

対話式アプリではライフサイクル設計が必要

アプリ起動 → 処理起動 → 一時停止 → 再開 → 処理停止 → アプリ終了
のように対話式でステータスを変更するアプリを開発するには、ライフサイクル設計をする必要がある。作っていて「処理停止」と「アプリ停止」が異なる概念と気づきました。

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
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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