正确的方法使用LINQ与CancellationToken

本文关键字:LINQ CancellationToken 方法 | 更新日期: 2023-09-27 18:02:13

我正在尝试编写一个LINQ查询,该查询将使用。net框架中提供的CancellationToken机制来支持取消。然而,目前还不清楚将取消和LINQ结合起来的正确方法是什么。

使用PLINQ,可以这样写:

 var resultSequence = sourceSequence.AsParallel()
                                    .WithCancellation(cancellationToken)
                                    .Select(myExpensiveProjectionFunction)
                                    .ToList();

不幸的是,WithCancellation()只适用于ParallelEnumerable -所以它不能与普通的旧LINQ查询一起使用。当然,可以使用WithDegreeOfParallelism(1)将并行查询转换为顺序查询—但这显然是一个hack:

 var resultSequence = sourceSequence.AsParallel()
                                    .WithDegreeOfParallelism(1)
                                    .WithCancellation(cancellationToken)
                                    .Select(myExpensiveProjectionFunction)
                                    .ToList();

我也想避免为这个操作创建一个单独的Task,因为我需要在几个地方这样做,我需要能够控制这个代码在某些情况下运行的线程。

所以,短写我自己的WithCancellation()的实现-是否有一个替代方案,将实现同样的事情?

正确的方法使用LINQ与CancellationToken

这个方法怎么样?

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