Самый простой вариант это использовать
Parallel.Foreach.
var myEntities = new MyEntity[100];
var maxThreads = 15;
System.Threading.Tasks.Parallel.ForEach(
myEntities,
new System.Threading.Tasks.ParallelOptions { MaxDegreeOfParallelism = maxThreads },
entity =>
{
entity.Do()
});
Второй вариант использовать
Semaphore или
SemaphoreSlim.
var myEntities = new MyEntity[100];
var maxThreads = 15;
var semaphoreSlim = new SemaphoreSlim(maxThreads);
var tasks = new List<Task>(myEntities.Length);
foreach (var entity in myEntities)
{
tasks.Add(Task.Run(() =>
{
semaphoreSlim.Wait();
try
{
entity.Do();
}
finally
{
semaphoreSlim.Release();
}
}));
}
Task.WaitAll(tasks.ToArray());
Если вы хотите использовать класс Thread напрямую, то
var myEntities = new MyEntity[100];
var maxThreads = 3;
var semaphore = new Semaphore(maxThreads, maxThreads);
var threads = new List<Thread>(myEntities.Length);
foreach (var entity in myEntities)
{
var thread = new Thread(() =>
{
semaphore.WaitOne();
try
{
entity.Do();
}
finally
{
semaphore.Release();
}
});
threads.Add(thread);
thread.Start();
}
foreach (var thread in threads)
thread.Join();
Хотя из условий задачи кажется, что здесь вполне можно обойтись Task. Task предпочтительней еще и по той причине, что потоки переиспользуются. Т.е. задействованных потоков будет столько, сколько одновременно выполняется задач, например 15. В случае же создания потока напрямую через класс Thread, 15 будут работать, остальные просто ждать, при этом все равно расходуя ресурсы.