Мне нужно выполнить много (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
s с обычной производительностью?