Выполнять несколько асинхронных задач непрерывно - PullRequest
0 голосов
/ 24 февраля 2020

Я хотел бы реализовать пул с заранее определенным числом (скажем, 10) асинхронных задач, выполняющихся бесконечно.

Используя Task.WhenAll , я могу легко запустить 10 задач, вставить их в список и вызвать await Task.WhenAll (list) в этом списке. Как только метод вернется, я снова смогу начать весь процесс на следующих 10 элементах. Проблема, с которой я сталкиваюсь в этом решении, заключается в том, что оно ожидает завершения самой длинной задачи перед циклом, что не является оптимальным.

Мне бы хотелось, чтобы при каждом завершении задачи запускалась новая. Тайм-аут также был бы хорош, чтобы предотвратить бесконечное выполнение задачи в случае сбоя.

Есть ли простой способ сделать это?

1 Ответ

3 голосов
/ 26 февраля 2020

Мне бы хотелось, чтобы при каждом выполнении задачи запускалась новая.

Это идеальный вариант использования для SemaphoreSlim:

private readonly SemaphoreSlim _mutex = new SemaphoreSlim(10);

public async Task AddTask(Func<Task> work)
{
  await _mutex.WaitAsync();
  try { await work(); }
  finally { _mutex.Release(); }
}

Было бы также хорошо использовать тайм-аут, чтобы предотвратить бесконечное выполнение задачи в случае сбоя.

Стандартным шаблоном для тайм-аутов является использование CancellationTokenSource в качестве таймер и передать CancellationToken в работу, которая должна поддерживать отмену:

private readonly SemaphoreSlim _mutex = new SemaphoreSlim(10);

public async Task AddTask(Func<CancellationToken, Task> work)
{
  await _mutex.WaitAsync();
  using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
  try { await work(cts.Token); }
  finally { _mutex.Release(); }
}
...