XavierAM
XavierAM

Reputation: 1775

Run multiple asynchronous Tasks continuously

I would like to implement a pool of a predetermined number (let's say 10) asynchronous tasks running undefinitely.

Using Task.WhenAll, I can easily start 10 tasks, feed them into a list, and call await Task.WhenAll(list) on this list. Once the method comes back, I can start again the whole process on the next 10 elements. The problem I face with this solution is that it waits for the longest task to complete before looping, which is not optimal.

What I would like is that anytime a task is completed, a new one is started. A timeout would be great as well, to prevent a task from being run undefinitely in case of a failure.

Is there any simple way of doing this?

Upvotes: 0

Views: 412

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456322

What I would like is that anytime a task is completed, a new one is started.

This is a perfect use case for SemaphoreSlim:

private readonly SemaphoreSlim _mutex = new SemaphoreSlim(10);

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

A timeout would be great as well, to prevent a task from being run undefinitely in case of a failure.

The standard pattern for timeouts is to use a CancellationTokenSource as the timer and pass a CancellationToken into the work that needs to support cancellation:

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(); }
}

Upvotes: 3

Related Questions