Существует ли эталонная реализация TaskPool? - PullRequest
0 голосов
/ 12 февраля 2019

Я собираюсь реализовать пул задач, где должно быть не более n Задачи выполняются в параллельном режиме.

Новые задания могут поступать из любого потока и использовать следующую бесплатную задачу.Если нет доступных задач, следует подождать, пока они не освободятся.Когда вся работа завершена, задачи должны «спать», чтобы не использовать процессорное время.

Есть ли что-то подобное в C # / .NET?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Вы можете легко использовать ConcurrentExclusiveSchedulerPair для него.Вот пример кода:

// max 3 parallel tasks
var schedulerPair = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, 3);
var factory = new TaskFactory(schedulerPair.ConcurrentScheduler);

Начинать новый Task следует с следующего кода :

factory.StartNew(() => create task here).Unwrap()

Полный пример:

static async Task Main(string[] args)
{
    var schedulerPair = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, 3);
    var factory = new TaskFactory(schedulerPair.ConcurrentScheduler);
    var tasks = new List<Task>();
    Random r = new Random();
    for (int i = 0; i < 5; i++)
    {
        var localI = i;
        var ts = TimeSpan.FromMilliseconds(1000 + r.Next(0, 10) * 100);
        var task = factory.StartNew(() => RunTask(localI, ts)).Unwrap();
        tasks.Add(task);
    }
    await Task.WhenAll(tasks);
}

static object mutex = new object();
static int numberOfParallelWorkers;

static async Task RunTask(int n, TimeSpan delay)
{
    for (int i = 0; i < 2; i++)
    {
        int nw;
        lock (mutex) { nw = numberOfParallelWorkers = numberOfParallelWorkers + 1; }
        var start = DateTime.Now;
        Console.WriteLine($"Started task #{n} part {i} at {start:ss.ff}, tasks: {nw}");
        Thread.Sleep(delay); // simulate CPU-bound work
        lock (mutex) { nw = numberOfParallelWorkers = numberOfParallelWorkers - 1; }
        var end = DateTime.Now;
        Console.WriteLine($"Finished task #{n} part {i} at {end:ss.ff}, parallel: {nw}");
    }
    await Task.Yield();
}

производит следующий вывод:

Started task #1 part 0 at 43.98, parallel: 2
Started task #0 part 0 at 43.98, parallel: 1
Started task #2 part 0 at 43.98, parallel: 3
Finished task #0 part 0 at 45.09, parallel: 2
Started task #0 part 1 at 45.09, parallel: 3
Finished task #1 part 0 at 45.29, parallel: 2
Started task #1 part 1 at 45.29, parallel: 3
Finished task #2 part 0 at 45.59, parallel: 2
Started task #2 part 1 at 45.59, parallel: 3
Finished task #0 part 1 at 46.19, parallel: 2
Started task #3 part 0 at 46.19, parallel: 3
Finished task #1 part 1 at 46.59, parallel: 2
Started task #4 part 0 at 46.59, parallel: 3
Finished task #2 part 1 at 47.19, parallel: 2
Finished task #4 part 0 at 47.59, parallel: 1
Started task #4 part 1 at 47.59, parallel: 2
Finished task #3 part 0 at 47.69, parallel: 1
Started task #3 part 1 at 47.69, parallel: 2
Finished task #4 part 1 at 48.59, parallel: 1
Finished task #3 part 1 at 49.19, parallel: 0
0 голосов
/ 12 февраля 2019

Я бы взглянул на блоки действий в библиотеке потоков данных TPL , которые предоставят вам желаемую функциональность.Я все время использую его в производственных средах с еще более сложными требованиями, которые вы указали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...