Управление потоками с помощью Task

#c# #multithreading #.net-4.0 #parallel-processing #multitasking

#c# #многопоточность #.net-4.0 #параллельная обработка #многозадачность

Вопрос:

В некотором коде, подобном этому

 for (int i = 0; i < length; i  ) //each iteration in another task
{
     Method2();

}
//Task.WaitAll()

public void Method2()
{
    Method3();
}

public void Method3()
{
    Method4();
}

public void Method4()
{
    process1.Start(); //this process take a lot of time so next iteration/next task should start in this place
}
  

Я бы хотел запускать каждую итерацию в другом потоке, но не все сразу. Один поток должен перейти к Method4(), запустить его и дождаться завершения этого процесса. Позже другой поток с таким же поведением и т.д. И в задаче.Программа WaitAll() должна дождаться всех потоков.

Как это сделать? 2 задачи на одной итерации, продолжить с помощью или sth?

Комментарии:

1. Вы не указали Метод1, а Метод2 присутствует дважды. Также укажите, выполняется ли какая-либо обработка с интенсивным использованием ЦП.

Ответ №1:

Не беспокойтесь.

Все итерации быстро заканчиваются выполнением Method4(), а вам нужен этот однопоточный.

При таком ограничении это вообще не сценарий для задач или потоков.


Но если предположить, что в Method2() и / или Method3() происходит что-то существенное, вы могли бы заменить for() цикл на Parallel.For() и использовать простой lock код процесса:

 private static object processLock = new object();  // probably static

public void Method4()
{
   lock(processLock)
   {
       process1.Start(); 
   }
}
  

Но теперь вы должны остерегаться того, чтобы TPL не создавал слишком много потоков. (используйте DegreeOfParallelism параллельно.Для).

Комментарии:

1. Нет, process1 занимает почти 1 час, поэтому я хочу запустить его несколько раз, чтобы лучше использовать процессор

2. Тогда, может быть, немного лучше объясните часть «не все сразу»? И удалите MethodX, когда у них здесь нет функции.

Ответ №2:

если я правильно понимаю, вы хотите запускать все эти процессы параллельно, но вы хотите ограничить количество процессов, которые будут выполняться одновременно, верно? Для этого вы можете использовать семафоры, которые ограничивают параллелизм (но имейте в виду, что все потоки будут находиться в ожидании все время — поэтому пометьте их как LongRunning).

другое дело, что вы должны дождаться завершения процесса в Method4.

 static SemaphoreSlim semaphore = new SemaphoreSlim (3); // Capacity of 3

List<Task> tasks = new List<Task>();
for (int i = 0; i < length; i  ) //each iteration in another task
{
     tasks.Add(Task.Factory.StartNew(() =>
     {
         Method2();
     }, 
     TaskCreationOptions.LongRunning);
}
Task.WaitAll(tasks)

public void Method2()
{
    Method3();
}

public void Method3()
{
    Method4();
}

public void Method4()
{
    semaphore.Wait();
    process1.Start(); 
    process1.WaitForExit();
    semaphore.Release();
}