Правильный способ использования LINQ с CancellationToken
Я пытаюсь написать запрос LINQ, который будет поддерживать отмену, используя механизм CancellationToken
, который предоставляется в платформе .NET. Тем не менее, неясно, как правильно сочетать отмену и LINQ.
С PLINQ можно написать:
var resultSequence = sourceSequence.AsParallel()
.WithCancellation(cancellationToken)
.Select(myExpensiveProjectionFunction)
.ToList();
К сожалению, WithCancellation()
применяется только к ParallelEnumerable
- поэтому он не может использоваться с простым старым запросом LINQ. Разумеется, можно использовать WithDegreeOfParallelism(1)
, чтобы превратить параллельный запрос в последовательный, но это явно хак:
var resultSequence = sourceSequence.AsParallel()
.WithDegreeOfParallelism(1)
.WithCancellation(cancellationToken)
.Select(myExpensiveProjectionFunction)
.ToList();
Я также хотел бы избежать создания отдельной Task
для этой операции, поскольку мне нужно сделать это в нескольких местах, и мне нужно иметь возможность контролировать, какой поток этот код работает в некоторых случаях.
Итак, не написав мою собственную реализацию WithCancellation()
- есть ли альтернатива, которая достигла бы того же самого?
Ответы
Ответ 1
Как насчет этого подхода?
var resultSequence = sourceSequence.WithCancellation(cancellationToken)
.Select(myExpensiveProjectionFunction)
.ToList();
static class CancelExtention
{
public static IEnumerable<T> WithCancellation<T>(this IEnumerable<T> en, CancellationToken token)
{
foreach (var item in en)
{
token.ThrowIfCancellationRequested();
yield return item;
}
}
}