Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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# 在同一查询中使用AsParallel()和AsSequential()的影响?C_C#_.net_Visual Studio_Linq_Plinq - Fatal编程技术网

C# 在同一查询中使用AsParallel()和AsSequential()的影响?C

C# 在同一查询中使用AsParallel()和AsSequential()的影响?C,c#,.net,visual-studio,linq,plinq,C#,.net,Visual Studio,Linq,Plinq,我在其中一本书中读到了PLINQ,它说: 如果您有一个可以从并行处理中受益的复杂查询 但也有一些部分应该按顺序完成,您可以使用 用于停止并行处理查询的断言 例如: var parallelResult = numbers.AsParallel().AsOrdered() .Where(i => i % 2 == 0).AsSequential(); 我想了解为什么允许这样做,以及对结果有什么影响?它是并行运行的吗?它是按顺序运行的吗?现在没有任何意义。您可以将LINQ查询概念化为

我在其中一本书中读到了PLINQ,它说:

如果您有一个可以从并行处理中受益的复杂查询 但也有一些部分应该按顺序完成,您可以使用 用于停止并行处理查询的断言

例如:

var parallelResult = numbers.AsParallel().AsOrdered()
    .Where(i => i % 2 == 0).AsSequential();

我想了解为什么允许这样做,以及对结果有什么影响?它是并行运行的吗?它是按顺序运行的吗?现在没有任何意义。

您可以将LINQ查询概念化为具有单个执行计划的原子构造,但将is概念化为包含多个数据流块的管道可能更有帮助。每个块的输出成为数据流中下一个块的输入,这些块一可用就同时处理项目。以下一个查询为例,该查询由两个Select运算符表示的两个块组成。第一块配置为一次并行处理3个项目,而第二块配置为按顺序处理每个项目。对于并行块,每个项目的处理持续时间为1000毫秒,对于顺序块,每个项目的处理持续时间为500毫秒:

var results = Partitioner
    .Create(Enumerable.Range(1, 10), EnumerablePartitionerOptions.NoBuffering)
    .AsParallel()
    .AsOrdered()
    .WithDegreeOfParallelism(3)
    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
    .Select(x =>
    {
        Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}"
            + $" [{Thread.CurrentThread.ManagedThreadId}] Parallel #{x}");
        Thread.Sleep(1000); // Simulate some CPU-bound work
        return x;
    })
    .AsSequential()
    .Select(x =>
    {
        Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}"
            + $" [{Thread.CurrentThread.ManagedThreadId}] Sequential #{x}");
        Thread.Sleep(500); // Simulate some CPU-bound work
        return x;
    })
    .ToArray();
Console.WriteLine($"Results: {String.Join(", ", results)}");
如果运行此代码,将得到如下输出:

08:32:17.628[4]平行线2 08:32:17.628[5]平行线1 08:32:17.628[6]平行3 08:32:18.642[6]平行5 08:32:18.642[5]平行4 08:32:18.644[4]平行6 08:32:18.651[1] 08:32:19.644[6]平行线7 08:32:19.645[4]平行8 08:32:19.646[5]平行9 08:32:19.654[1]2 08:32:20.156[1]3 08:32:20.648[4]平行10 08:32:20.658[1]4 08:32:21.161[1]5 08:32:21.663[1]6 08:32:22.164[1]7 08:32:22.672[1]8 08:32:23.173[1]9 08:32:23.675[1]10 结果:1,2,3,4,5,6,7,8,9,10 请注意,在所有并行处理完成之前,顺序处理是如何开始的。为了达到这个效果,我使用了配置选项和,以防止第一个块缓冲其输入和输出

为了完整起见,让我们使用库重写此查询。代码变得更加冗长和流畅,但执行控制变得更加精确,异步工作流也变得可用PLINQ不支持异步:

var block1 = new TransformBlock<int, int>(async x =>
{
    Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}"
        + $" [{Thread.CurrentThread.ManagedThreadId}] Parallel #{x}");
    await Task.Delay(1000); // Simulate some I/O operation
    return x;
}, new ExecutionDataflowBlockOptions()
{
    MaxDegreeOfParallelism = 3,
    EnsureOrdered = true // redundant since EnsureOrdered is the default
});

var block2 = new TransformBlock<int, int>(async x =>
{
    Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}"
        + $" [{Thread.CurrentThread.ManagedThreadId}] Sequential #{x}");
    await Task.Delay(500); // Simulate some I/O operation
    return x;
}); // MaxDegreeOfParallelism = 1 is the default

block1.LinkTo(block2, new DataflowLinkOptions() { PropagateCompletion = true });

// Feeding the first block
foreach (var x in Enumerable.Range(1, 10))
{
    await block1.SendAsync(x);
}
block1.Complete();

var results = new List<int>(); // Collecting the results is a bit painful
while (await block2.OutputAvailableAsync())
{
    while (block2.TryReceive(out var result))
    {
        results.Add(result);
    }
}
await block2.Completion;
Console.WriteLine($"Results: {String.Join(", ", results)}");

内存中的代码i%2==0,其中lambda将在多个线程中并行运行。这是你想要的吗?查询结束时的AsSequential没有影响,因为之后不会再进行计算。@TheodorZoulias我想知道将这两个方法调用在一起是否有好处。这是一个例子,以防。。。。例如,如果要获取数据,可以并行获取所有数据。现在这很好,而且比按顺序做要快。但有时你需要做更多的逻辑,一个接一个地评估每个值。例如,在订购过程中。您将无法执行此并行操作,因为您需要保留在查询的前一个子句中建立的顺序。关于AsParallel和AsSequential,也许你可以参考