Правильный способ использования LINQ с CancellationToken - PullRequest
10 голосов
/ 15 июля 2011

Я пытаюсь написать запрос 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 Ответ

32 голосов
/ 15 июля 2011

Как насчет этого подхода?

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;
        }
    }
}
...