C# TaskCanceledException上的低性能
我需要并行运行许多(10-100k)转换操作。在这种情况下,我使用C# TaskCanceledException上的低性能,c#,async-await,task,cancellation,cancellationtokensource,C#,Async Await,Task,Cancellation,Cancellationtokensource,我需要并行运行许多(10-100k)转换操作。在这种情况下,我使用tasks,symaphoresim来控制并行度,并使用CancellationTokenSource来防止在引发异常时不运行要运行的任务。 我正在尝试这样做: var tasks = table.Body.Select(async row => { await _semaphore.WaitAsync(_cts.Token).ConfigureAwait(false)
tasks
,symaphoresim
来控制并行度,并使用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来实现常规性能?当您的代码执行\u信号量.WaitAsync(\u cts.Token)
时,信号量必须设置可取消的等待;这意味着它必须注册取消令牌,当发出信号时,将等待从等待队列中移除。因此,是的,我预计10万注册会出现性能问题
如果你不需要取消等待,我不会
await _semaphore.WaitAsync().ConfigureAwait(false);
_cts.Token.ThrowIfCancellationRequested();
Convert
引发异常有多常见?如果没有抛出异常,我希望这两个具有相似的性能。毕竟,WaitAsync()
只调用WaitAsync(Timeout.Infinite,default(CancellationToken))
WaitAsync
还有一个快捷方式,CancellationToken
已经被取消。什么数据类型是表
?您能否向我们展示Convert
的功能?另外,在您的第二个示例中,在获取信号量之前,在方法的最顶端检查\u cancelled
。因此,我希望每行的Select
调用在任何一行都有机会获得调用锁Convert
之前检查\u cancelled
,因此我认为取消在这里不可能起作用,正如您所描述的那样。@AndreyAlonzovConvert
做什么?为什么不使用专门为数据并行而构建的Parallel.ForEach
或PLINQ?并行处理是一回事。并发执行有些非常不同。@AndreyAlonzov您还没有发布关于Convert
的任何信息。这很重要。如果未向方法传递取消令牌,则无法取消运行Convert
方法。问题不在于取消令牌Convert
本身会忽略取消,无论您使用什么库,它都会继续忽略取消。谢谢,@Stephen!即使我试图直接抛出一个异常,也是一样的。在版本构建中,它需要很长的时间(大约是使用布尔标记的10倍),但比调试中快得多。