Правильный способ использования LINQ с CancellationToken
Я пытаюсь написать запрос LINQ, который будет поддерживать отмену, используя CancellationToken
механизм, который предоставляется в.NET Framework. Тем не менее, неясно, каким будет правильный способ комбинирования отмены и 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;
}
}
}