.NET
優先順位などの細かい制御は必要とせず、手が空いた時にとりあえず実行すれば良い程度の非同期処理の場合、非同期デリゲートはお手軽で便利だ。.NET Framework 2.0 の時点で、非同期デリゲートの既定同時実行数は「CPU 数 x 25」なので、最近のデュアルコアプロセッサであれば、何も考えなくても 50 まで同時に実行される。
しかし、50 スレッドというのはどう考えても多すぎる。スレッドの切り替え自体、ある程度コストのかかるものだし、ネットワークやデータベースのコネクションを消費するのであれば、同時実行数はせいぜい 10 以下に抑えたいという場合もある(10 にたいして意味はない)。そういう場合は、ThreadPool.QueueUserWorkItem メソッドに処理するメソッドを渡し、ThreadPool.SetMaxThreads メソッド(※1)で最大スレッド数を決めれば良いのだが、ThreadPool.QueueUserWorkItem を使ってしまうと、メソッドの引数に強度がなくなる(引数が Object になるため)。
ところが、そもそも非同期デリゲートは ThreadPool からスレッドを拝借しているので、ThreadPool の最大数さえ決めてしまえば、非同期デリゲートの同時実行数も自ずと抑えられる。非同期デリゲートを使う場合、最大実行数の考慮が疎かになりがちなので、この辺は押さえておきたい。
下記は、10 までしか非同期デリゲートが起動しない例。
using System;
class Program
{
delegate void ThreadDelegate(int num);
static void Main(string[] args)
{
System.Threading.ThreadPool.SetMaxThreads(10, 1000);
for(int i = 0; i < 100; i++)
{
new ThreadDelegate(Func).BeginInvoke(i + 1, null, null);
}
System.Threading.Thread.Sleep(Timeout.Infinite);
}
static void Func(int num)
{
Console.WriteLine(String.Format("Start! {0}", num));
System.Threading.Thread.Sleep(Timeout.Infinite);
}
}
※1 .NET Framework 1.1 の場合、mscoree.dll にある CorSetMaxThreads を使わないとスレッドプールの最大数を変更できなかった。ハッキリ言って、これを使うのは面倒。