TaskCanceledException的性能低下

时间:2019-03-26 12:41:07

标签: c# async-await task cancellation cancellationtokensource

我需要并行运行许多(10-100k)转换操作。在这种情况下,我使用tasksSymaphoreSlim控制并行度,并使用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

1 个答案:

答案 0 :(得分:0)

当您的代码执行_semaphore.WaitAsync(_cts.Token)时,信号量必须设置可取消的等待;这意味着它必须向取消令牌注册,并在收到信号时将其从等待队列中删除。所以,是的,我希望10万次注册会出现性能问题。

如果您不需要取消等待,我不会。

await _semaphore.WaitAsync().ConfigureAwait(false);
_cts.Token.ThrowIfCancellationRequested();