Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LINQ和CancellationToken的正确方法_C#_.net_Linq_Parallel Processing_Cancellation - Fatal编程技术网

C# 使用LINQ和CancellationToken的正确方法

C# 使用LINQ和CancellationToken的正确方法,c#,.net,linq,parallel-processing,cancellation,C#,.net,Linq,Parallel Processing,Cancellation,我正在尝试使用.NET framework中提供的机制编写一个支持取消的LINQ查询。然而,目前还不清楚将取消和LINQ结合起来的正确方法是什么 使用PLINQ,可以编写: var resultSequence = sourceSequence.AsParallel() .WithCancellation(cancellationToken) .Sel

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

使用PLINQ,可以编写:

 var resultSequence = sourceSequence.AsParallel()
                                    .WithCancellation(cancellationToken)
                                    .Select(myExpensiveProjectionFunction)
                                    .ToList();
不幸的是,它只适用于
可并行枚举的
——因此不能与普通的旧LINQ查询一起使用。当然,可以使用将并行查询转换为顺序查询,但这显然是一种黑客行为:

 var resultSequence = sourceSequence.AsParallel()
                                    .WithDegreeOfParallelism(1)
                                    .WithCancellation(cancellationToken)
                                    .Select(myExpensiveProjectionFunction)
                                    .ToList();
我还希望避免为此操作创建单独的
任务
,因为我需要在多个位置执行此操作,并且在某些情况下,我需要能够控制此代码在哪个线程上运行


那么,除了编写自己的
with cancellation()
实现之外,还有其他方法可以实现同样的效果吗?

这种方法怎么样

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;
        }
    }
}
var resultSequence=sourceSequence.WithCancellation(cancellationToken)
.选择(myExpensiveProjectionFunction)
.ToList();
静态类扩展
{
公共静态IEnumerable with Cancellation(此IEnumerable en,CancellationToken令牌)
{
foreach(英语中的var项目)
{
token.ThrowIfCancellationRequested();
收益回报项目;
}
}
}

这实际上值得成为Connect上的一个功能请求。我不太清楚这是否有任何影响,或者这是否有效,或者是否可以与AsParallel()一起使用,但我喜欢这个解决方案的简单性,所以我决定升级。如果我将其更改为
返回en.TakeWhile(p_item=>!token.iscancellationrequest)
会对性能产生任何影响吗?我知道这个问题很久以前就有了,但是仅仅使用
aspallel().WithCancellation(cancellationToken)
并让它成为PLINQ有什么错?