我需要并行运行许多(10-100k)转换操作。在这种情况下,我使用tasks
,SymaphoreSlim
控制并行度,并使用CancellationTokenSource
防止抛出异常时无法运行的任务运行。
我正在尝试做这样的事情:
var tasks = table.Body.Select(async row =>
{
await _semaphore.WaitAsync(_cts.Token).ConfigureAwait(false);
try
{
await Convert(row, preparedData, table, mapper).ConfigureAwait(false);
}
catch (Exception)
{
_cts.Cancel();
throw;
}
});
await Task.WhenAll(tasks).ConfigureAwait(false);
但是性能太差了。如果我摆脱使用令牌的麻烦,只需几秒钟。
var tasks = table.Body.Select(async row =>
{
if (_canceled)
return;
await _semaphore.WaitAsync().ConfigureAwait(false);
try
{
await Convert(row, preparedData, table, mapper).ConfigureAwait(false);
}
catch (Exception)
{
_canceled = true;
throw;
}
});
await Task.WhenAll(tasks).ConfigureAwait(false);
有没有办法以正常表现使用CancellationToken
?
答案 0 :(得分:0)
当您的代码执行_semaphore.WaitAsync(_cts.Token)
时,信号量必须设置可取消的等待;这意味着它必须向取消令牌注册,并在收到信号时将其从等待队列中删除。所以,是的,我希望10万次注册会出现性能问题。
如果您不需要取消等待,我不会。
await _semaphore.WaitAsync().ConfigureAwait(false);
_cts.Token.ThrowIfCancellationRequested();