パラメーターのある Task の利用 (戻り値が無い場合)

パラメーターをTaskに渡しますが、戻り値が無い場合の Task のコードを紹介します。

概要

Taskにパラメータを渡す場合は、Taskの作成時のコンストラクタの第二引数にパラメーターを与えます。

プログラム1 : メソッドを利用してTaskオブジェクトを作成する場合

UI


コード

下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SimpleTask
{
  public partial class FormTaskActionParam : Form
  {
    public FormTaskActionParam()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      string str1 = "ぺんぎん";
      string str2 = "あひる";

      Task task1 = new Task(proc, (object)str1);
      Task task2 = new Task(proc, (object)str2);

      task1.Start();
      task2.Start();
    }

    private void proc(object param)
    {
      System.Threading.Thread.Sleep(2000);
      string parameter_string = "";

      if (param != null) {
        parameter_string = (string)param;
      }

      MessageBox.Show("Proc1が完了しました。" + parameter_string);
    }
  }
}

解説

ボタンクリックで以下のコードを実行します。Taskに渡すパラメーターを準備します。 その後、Taskを作成します。Taskのコンストラクタの第一引数に実行するメソッド(デリゲート)を与えます。第二引数にTaskへ渡すパラメータを与えます。
  string str1 = "ぺんぎん";
  string str2 = "あひる";

  Task task1 = new Task(proc, (object)str1);
  Task task2 = new Task(proc, (object)str2);

作成されたTaskオブジェクトのStart メソッドを呼び出しTaskの処理を実行開始します。
  task1.Start();
  task2.Start();

Taskで実行されるメソッドは下記コードです。Sleepメソッドを呼び出しスレッドを停止させロック状態にします。
その後、param 変数からTaskに渡されたパラメータを取得します。パラメータはobject型で渡されるため、キャストして利用します。
最後に、メッセージボックスを表示し、「Proc1が完了しました。」の文字列とTaskに渡されたパラメーターの値をメッセージボックスに表示します。
private void proc(object param)
{
  System.Threading.Thread.Sleep(2000);
  string parameter_string = "";

  if (param != null) {
    parameter_string = (string)param;
  }

  MessageBox.Show("Proc1が完了しました。" + parameter_string);
}

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。[button1]をクリックします。


クリック後、2秒ほどすると、2つダイアログボックスが表示されます。 ダイアログ表示までの間スレッドが停止していますが、Taskで別スレッドで動作しているため、 メインウィンドウは固まらずに操作を続けられることが確認できます。
表示されたダイアログボックスのメッセージにTask作成時に与えた文字列が 表示されていることが確認できます。


それぞれのダイアログに別のメッセージが表示されることも確認できます。

プログラム2 : ラムダ式を利用してTaskオブジェクトを作成する場合

ラムダ式を利用してパラメーターを与えられるTaskオブジェクトを作成します。

UI

先ほどのUIにボタンを追加します。(Button3 のみを利用します。)

コード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SimpleTask
{
  public partial class FormTaskActionParam : Form
  {
    public FormTaskActionParam()
    {
      InitializeComponent();
    }

    private void button3_Click(object sender, EventArgs e)
    {
      string param1 = "ぺんぎん";
      string param2 = "あひる";

      Task t1 = new Task((p1) => proc(p1), param1);
      Task t2 = new Task((p2) => proc(p2), param2);
      t1.Start();
      t2.Start();
    }

    private void proc(object param)
    {
      System.Threading.Thread.Sleep(2000);
      string parameter_string = "";

      if (param != null) {
        parameter_string = (string)param;
      }

      MessageBox.Show("Proc1が完了しました。" + parameter_string);
    }

  }
}

解説

"プログラム1" のコードと似ていますが、Taskオブジェクト作成時のコンストラクタの引数にメソッドの名称ではなくラムダ式を与えています。
今回のコードのラムダ式は、引数を1つ持つメソッドで、実行時にprocメソッドを呼び出す動作のラムダ式になります。ラムダ式の詳細については、こちらの記事を参照して下さい。

Taskオブジェクトを2つ作成し、一つ目のt1 Taskには param1 の文字列をパラメーターに与え、もう一つの t2 Taskには param2 の文字列をパラメーターに与えています。
Taskオブジェクトの実行は先のプログラムと同様に Start メソッドを呼び出して実行開始します。
  string param1 = "ぺんぎん";
  string param2 = "あひる";

  Task t1 = new Task((p1) => proc(p1), param1);
  Task t2 = new Task((p2) => proc(p2), param2);
  t1.Start();
  t2.Start();

実行結果

プロジェクトを実行します。ウィンドウが表示されますので[button3]をクリックします。先のプログラムと同じ動作になり、 メッセージダイアログが2つ表示され、それぞれのダイアログのメッセージにパラメーターとして渡された文字列が表示されます。

補足 : Task.Runメソッドを利用する場合

引数も戻り値もない、Action型の場合はRunメソッドで実行する記述ができますが、引数がある場合 Action の型を取れるRunメソッドが無いため、 Runメソッドを利用した記述はできません。次セクションのラムダ式を利用する記述などに変える必要があります。
コンパイルエラーになるコード
private void button2_Click(object sender, EventArgs e)
{
  Task.Run((Action<string>)proc);
  Task.Run((Action<string>)proc);
}
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2021-08-24
作成日: 2020-05-06
iPentec all rights reserverd.