I need to run many (10-100k) convertation operations in parallel. In this case I use tasks
, SymaphoreSlim
to control degree of parallelism and CancellationTokenSource
to prevent not running tasks to run when exception is thrown.
I'm trying to do something like this:
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);
But performance is awful. If I get rid of using tokens it takes just a few seconds.
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);
Is there a way to use CancellationToken
s with a regular performance?
>`. Convert does some convertation logic, throws custom exception on error and releases the symaphore.
– Andrey Alonzov Mar 26 '19 at 12:52