@Xveeder

Как ограничить количество одновременно запускаемых потоков?

Доброго времени суток, товарищи.

Возник вопрос. Например, у меня есть 100 определённых сущностей, которые выполняют определённые действия. Я хочу запустить их в многопотоке, но чтобы одновременно работало не более 15 потоков, и в то время, когда определённая сущность вышла из потока (т.е. выполнила свой таск), в этот поток зашла сразу новая.

Как это сделать (при работе с thread)? На первый взгляд, наиболее простым методом является семафор. Но правильно ли?
Спасибо.
  • Вопрос задан
  • 2655 просмотров
Решения вопроса 1
@basrach
Самый простой вариант это использовать 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 будут работать, остальные просто ждать, при этом все равно расходуя ресурсы.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы