C#の非同期処理の基本であるThreadを利用する
C#で非同期処理をするには、Thread、Task、async/awaitを使うなどいくつかの方法があります。中でもThreadを使った非同期処理はもっとも基本的でレガシーなやり方です。サンプルコードはコンソールアプリです。
目次 Table of Contents
Threadの使い方
Threadを使った非同期の基本形です。生成されたスレッドごとに振られるスレッドIDを確認すると、確かに別スレッドで処理が実行されていることが分かります。
Console.WriteLine(“スレッドID : ” + Thread.CurrentThread.ManagedThreadId + ” in Main”);
Thread thread1 = new Thread(new ThreadStart(() =>
{
Console.WriteLine(“処理開始”);
Console.WriteLine(“スレッドID : ” + Thread.CurrentThread.ManagedThreadId + ” in Thread”);
Thread.Sleep(3000);
Console.WriteLine(“処理終了”);
}));
thread1.Start();
実際にはStart()の直後にJoin()を書くとそれ以降の処理に進まずただの同期処理と変わらなくなってしまいますので、結果が必要となる部分で呼び出します。
スレッドにパラメータを与えて結果を受け取る
スレッドにパラメータを与えて動的に処理結果を変える方法です。ParameterizedThreadStartデリゲートを利用することで可能です。Threadのコンストラクタに引数ありのメソッド名を指定し、Thread.Startメソッドの引数にパラメータを与えます。
→Microsoft 公式ドキュメント
static void Main(string[] args)
{
Thread thread1 = new Thread(HeavyMethod1);
thread1.Start(“Hello”);
}
static void HeavyMethod1(object data)
{
Console.WriteLine(“HeavyMethod1() start”);
Thread.Sleep(5000);
Console.WriteLine(data + ” C#”);
Console.WriteLine(“HeavyMethod1() finish”);
}
ただしParameterizedThreadStartデリゲートは引数がobject型となり型セーフではありません。クラスのコンストラクタにパラメータを指定する方法が推奨されているようです。
class Program{
static void Main(string[] args)
{
MyThread myThread = new MyThread(“Hello”);
Thread thread1 = new Thread(new ThreadStart(myThread.Run));
thread1.Start();
thread1.Join();
Console.WriteLine(“結果 : ” + myThread.ResultStr);
}
}
class MyThread
{
private string receivedStr = “”;
private string resultStr = “”;
public MyThread(string str) {
this.receivedStr = str;
}
private string ReceivedStr
{
get { return this.receivedStr; }
}
public string ResultStr
{
get { return this.resultStr; }
set { this.resultStr = value; }
}
public void Run()
{
Console.WriteLine(“MyThread.Run() start”);
Thread.Sleep(5000);
ResultStr = ReceivedStr + ” Thread!”;
Console.WriteLine(“MyThread.Run() finish”);
}
}