佐々木屋

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

非同期処理、マルチスレッド(ThreadPool)

<ThreadPoolクラスの基本>

前回Threadクラスを用いた非同期処理を説明しましたが、スレッドの新規作成は思っている以上にコストがかかります。スレッドは生成だけではなく破棄される時もコストがかかるので、頻繁に使用すると処理がとても重くなってしまいます。
あまりThreadを増やし過ぎたり同時実行が多すぎると、シングルスレッドの時より処理が遅くなってしまう事も・・・。

それを改善した手法がThreadPoolクラスです。プールはプログラミング用語で良く出てきますが、その名の通り「Threadの置き場」という感じでしょうか。あらかじめ生成したスレッドを破棄せず保留しておき、必要になったら使いまわすといった感じ(ワーカープロセスみたいな)。効率よく処理を実行することが可能になります。

public static void Main() {
    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(HeavyProc));
    for (int i = 0; i <= 5; ++i) {
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine("Piyo");
    }
}
private void HeavyProc(object obj) {
    for (int i = 0; i <= 5; ++i) {
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine("Hoge");
    }
}
 Public Shared Sub Main()
    System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf HeavyProc))
    For i As Integer = 0 To 5
        System.Threading.Thread.Sleep(1000)
        Console.WriteLine("Piyo")
    Next
End Sub
Private Sub HeavyProc(ByVal obj As Object)
    For i As Integer = 0 To 5
        System.Threading.Thread.Sleep(1000)
        Console.WriteLine("Hoge")
    Next
End Sub

結果はThreadクラスと同様です。

Piyo
Hoge
Piyo
Hoge
Piyo
Hoge
Piyo
Hoge
Piyo
Hoge
Piyo
Hoge

なお、ThreadPoolクラスはバックグラウンドで処理されます。
ThreadPoolクラスQueueUserWorkItemメソッドによりThreadPoolキューにメソッド(ここではHeavyProc)が追加されます。追加されたキューは先入れ先出しFIFO)で効率よく処理されます。

因みに、.NET Framework4よりスレッドプールの再構築・再設計が行われ、従来に比べてより効率よく処理されるようになっています。