• Pro LINQ 之六:并行LINQ查询


    写在前面

    《Pro LINQ in C# 2010》第22章开始,讲的是Parallel LINQ,即并行LINQ查询,简称PLINQ。这本是LINQ的一个重大改进和提升,但该书却在这一重大主题上草草结束。作为入门,我更喜欢MSDN上的一篇文章:在多核处理器上运行查询

    PLINQ概要

    PLINQ属于LINQ to Objects,将IEnumerable<T>类型的序列用AsParallel()运算符转换为ParallelQuery<T>,即可自动激活并行LINQ查询。

    PLINQ的核心在于分页——将待查询的序列按CPU核心数量分为若干页,交给各CPU进行运算。

    若没有定序运算符AsOrdered(),则PLINQ返回的查询结果是乱序的、不可靠的(Unstable),多数情况下是按分页顺序取出查询结果。但使用AsOrdered()也是有代价的,因为要重新排序,因此可能抵消使用PLINQ的收益。

    多数情况下,PLINQ会自主决定是否采用并行计算。使用WithExecutionMode(ParallelExecutionMode.ForceParallelism)方法,可以强制使用并行查询。

    使用WithDegreeOfParallelism(),可以限定并行的分页数,简单地可理解为交给几个CPU核心计算。

    PLINQ中的异常处理

    区别于通常的串行查询在遇到异常后停止查询,PLINQ中的每个分支是独立的,某个分支发生异常,只会导致该分支的查询被中断。

    PLINQ会将每个并行分支中发生的异常收集并封装在异常System.AggregateException里,并在PLINQ查询得到实际执行时被抛出。因此我们要做的,就是利用try-catch捕获异常AggregateException。而在AggregateException内部,提供有一个方法Handle()用以依次处理从各分支中搜集到的异常。该方法的参数为一委托,可以用lambda表达式实现。该委托的返回类型为bool:如果异常被我们处理了,则返回true;如果异常靠我们自己处理不了,就返回false。就象作者在示例中的如下处理方式:

    IEnumerable<string> results = presidents
                .AsParallel()
                .Select(p =>
                {
                    if (p == "Arthur" || p == "Harding")
                        throw new Exception(String.Format("Problem with President {0}", p));
                    return p;
                });
    
    try
    {
        foreach (string president in results)
        {
            Console.WriteLine("Result: {0}", president);
        }
    }
    catch (AggregateException agex)
    {
        agex.Handle(ex =>
        {
            Console.WriteLine(ex.Message);
            return true;
        });
    }

    通过在select选择子中的lambda表达式抛出异常,然后在try-catch块中捕获,再利用捕获到的AggregateException方法Handle()依次取出其中搜集到的异常。Handle()方法的参数有两个,一个是搜集到的异常,一个是Func<>(可以用Lambda表达式实现)。

    PLINQ的其他操作

    Range()

    Repeat()

    Empty()

    与LINQ to Object的类似。

    AsOrdered()

    按源序列中的先后顺序返回查询结果

    AsUnordered()

    相当于Undo AsOrdered()

    AsParallel()

    转换成ParallelQuery<T>

    AsSequential()

    AsEnumerable()

    作用与AsParallel()相反

    WithDegreeOfParallelism(int degree)

    设置分页数

    WithExecutionMode(ParallelExecutionMode)

    是否强制启动并行查询

    Default:由PLINQ决定是否启动并行查询

    ForceParallelism:强调启动并行查询

    WithMergeOptions(ParallelMergeOptions)

    返回查询结果的时机

    NotBuffered:产生结果即刻返回

    FullyBuffered:待全部结果产生后才返回

    AutoBuffered/Default:由PLINQ决定Buff大小,并在Buff填满时返回结果

    Cast()

    OfType()

    类似LINQ to Objects中的操作

    ForAll()

    类似泛型的ForEach()


    (全书完)

  • 相关阅读:
    visitortheoryreflection.cs
    adaptertheory.cs
    factorymethodavocados.cs
    compositetheorynswithShare.cs
    在.NET/Mono上运行Java:Jeroens Frijters谈IKVM.NET
    Building ASP.NET Server ControlsTextbox.cs
    compositephotolibrary.cs
    proxyspacebook.cs
    adapterpluggabletheory.cs
    Building ASP.NET Server ControlsFancyLabel.cs
  • 原文地址:https://www.cnblogs.com/Abbey/p/2122820.html
Copyright © 2020-2023  润新知