我想实现一个预定数目(比如说10个)的无限期运行的异步任务的池。
使用Task.WhenAll,我可以轻松地启动10个任务,将它们输入一个列表,然后在此列表上调用await Task.WhenAll(list)。一旦方法回来,我就可以在接下来的10个元素上重新开始整个过程。我用此解决方案面临的问题是,它在循环之前要等待最长的任务完成,这不是最佳选择。
我想要的是,只要任务完成,就会开始一个新任务。超时也很重要,以防止在失败的情况下无限期地运行任务。
是否有任何简单的方法?
我想要的是,只要任务完成,就会开始一个新任务。
这是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(); }
}