佐々木屋

技術的なことから趣味まで色々書きます

非同期処理、マルチスレッド(Task①基本)

ThreadPoolの概念を引き継ぎ、より改良された非同期処理クラスとして .NET Framework4.0以降に登場したのがTaskクラスです。
Taskクラスはスレッドプールを利用しますが、生成・管理は全てクラス側が勝手にやってくれますので、特に意識する必要はありません。

Taskの実行は
・Startメソッドによる実行
・FactoryオブジェクトのStartNewメソッドによる実行
・Runメソッドによる実行
の3種類があります。

さて、どれを選択するかというと、StartメソッドはTaskクラスの中で一番古い手法で、行数も他に比べて多く、機能も限定的なので利用すべきではありません。

結論から言えばRunメソッドを利用すべきです。機能だけで言えば「Run」<「StartNew」ですが、そもそもRunメソッドはStartNewメソッドを改良したもので、余程特殊な使い方をしない限りはRunメソッドの方が有利です。但し、Runメソッドは.NET Framework4.5以上が必要ですので、VS2010などを利用している場合は必然的にStartNewメソッドを選択することになります。


Taskを実行する方法は、以下の3通りがあります。個人的にはラムダ式を利用した方がすっきり書けるのでおすすめですが、VB.NETラムダ式は無駄に長くなる可能性があるので、デリゲートによる方法のほうがいいかもしれません。
・メソッドを指定(StartNewメソッドのみ)
・匿名メソッドを利用
ラムダ式を利用

public void HeavyProc() {
    for (int i = 0; i <= 5; ++i) {
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine("Hoge");
    }
}

public void Main() {
    //Startメソッド(非推奨)
    {
        Task t = new Task(HeavyProc);
        t.Start();
    }


    //StartNewメソッド(.NET Framework4.5未満まで推奨)
    {
        //メソッドを指定
        Task t = Task.Factory.StartNew(HeavyProc);
    }
    {
        //匿名メソッド
        Task t = Task.Factory.StartNew(delegate {HeavyProc();});
    }
    {
        //ラムダ式
        Task t = Task.Factory.StartNew(() => HeavyProc());
    }


    //Rnuメソッド(.NET Framework4.5以上で推奨)
    {
        //匿名メソッド
        Task t = Task.Run(delegate {HeavyProc();});
    }
    {
        //ラムダ式
        Task t = Task.Run(() => HeavyProc());
    }
}
Public Sub HeavyProc()
    For i As Integer = 0 To 5
        System.Threading.Thread.Sleep(1000)
        Console.WriteLine("Hoge")
    Next
End Sub

Public Sub Main()
    'Startメソッド(非推奨)
    Dim task As Task = New Task(AddressOf HeavyProc)
    task.Start()


    'StartNewメソッド
    'デリゲートインスタンス(VB.NETは匿名メソッドが無い)
    Dim task_s1 As Task = Task.Factory.StartNew(AddressOf HeavyProc)
    
    'ラムダ式
    Dim task_s2 As Task = Task.Factory.StartNew(
            Sub()
                HeavyProc()
            End Sub)


    'Runメソッド
    'デリゲートインスタンス(VB.NETは匿名メソッドが無い)
    Dim task_s1 As Task = Task.Run(AddressOf HeavyProc)
    
    'ラムダ式
    Dim task_s2 As Task = Task.Run(
            Sub()
                HeavyProc()
            End Sub)
End Sub