使用LINQ和CancellationToken的正确方法

时间:2011-07-14 21:28:07

标签: c# .net linq parallel-processing cancellation

我正在尝试编写一个LINQ查询,该查询支持使用.NET框架中提供的CancellationToken机制进行取消。但是,目前还不清楚将取消和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,因为我需要在几个地方执行此操作,并且我需要能够在某些情况下控制此代码运行的线程。< / p>

因此,如果没有编写我自己的WithCancellation()实现 - 有没有可以达到同样效果的替代方案?

1 个答案:

答案 0 :(得分:32)

这种做法怎么样?

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