方法: 単純な PLINQ クエリを作成して実行する

この記事の例では、ソース シーケンスに対する ParallelEnumerable.AsParallel 拡張メソッドを使用して単純な並列統合言語クエリ (LINQ) クエリを作成し、ParallelEnumerable.ForAll メソッドを使用して、そのクエリを実行する方法を示します。

注意

ここでは、ラムダ式を使用して PLINQ でデリゲートを定義します。 C# または Visual Basic のラムダ式についての情報が必要な場合は、「Lambda Expressions in PLINQ and TPL (PLINQ および TPL のラムダ式)」を参照してください。

using System;
using System.Linq;

class ExampleForAll
{
    public static void Main()
    {
        var source = Enumerable.Range(100, 20000);

        // Result sequence might be out of order.
        var parallelQuery =
            from num in source.AsParallel()
            where num % 10 == 0
            select num;

        // Process result sequence in parallel
        parallelQuery.ForAll((e) => DoSomething(e));

        // Or use foreach to merge results first.
        foreach (var n in parallelQuery)
        {
            Console.WriteLine(n);
        }

        // You can also use ToArray, ToList, etc as with LINQ to Objects.
        var parallelQuery2 =
            (from num in source.AsParallel()
             where num % 10 == 0
             select num).ToArray();

        // Method syntax is also supported
        var parallelQuery3 =
            source.AsParallel()
                .Where(n => n % 10 == 0)
                .Select(n => n);

        Console.WriteLine("\nPress any key to exit...");
        Console.ReadLine();
    }

    static void DoSomething(int _) { }
}

Public Class Program
    Public Shared Sub Main()
        Dim source = Enumerable.Range(100, 20000)

        ' Result sequence might be out of order.
        Dim parallelQuery = From num In source.AsParallel()
                            Where num Mod 10 = 0
                            Select num

        ' Process result sequence in parallel
        parallelQuery.ForAll(Sub(e)
                                 DoSomething(e)
                             End Sub)

        ' Or use For Each to merge results first
        ' as in this example, Where results must
        ' be serialized sequentially through static Console method.
        For Each n In parallelQuery
            Console.Write("{0} ", n)
        Next

        ' You can also use ToArray, ToList, etc, as with LINQ to Objects.
        Dim parallelQuery2 = (From num In source.AsParallel()
                              Where num Mod 10 = 0
                              Select num).ToArray()

        ' Method syntax is also supported
        Dim parallelQuery3 =
            source.AsParallel().Where(Function(n)
                                          Return (n Mod 10) = 0
                                      End Function).Select(Function(n)
                                                               Return n
                                                           End Function)

        For Each i As Integer In parallelQuery3
            Console.Write($"{i} ")
        Next


        Console.WriteLine()
        Console.WriteLine("Press any key to exit...")
        Console.ReadLine()
    End Sub

    ' A toy function to demonstrate syntax. Typically you need a more
    ' computationally expensive method to see speedup over sequential queries.
    Shared Sub DoSomething(ByVal i As Integer)
        Console.Write($"{Math.Sqrt(i):###.##} ")
    End Sub
End Class

この例では、結果シーケンスの順序付けが重要ではない場合に、並列 LINQ クエリを作成して実行する基本的なパターンを示しています。 通常、順序なしのクエリは、順序ありのクエリより高速です。 このクエリはソースを、複数のスレッドで非同期的に実行した複数のタスクにパーティション分割します。 各タスクが完了する順序は、その特定のパーティションに含まれる要素を処理するために必要な作業量だけでなく、オペレーティング システムが各スレッドをどのようにスケジュールするかといった外部要因にも依存します。 この例は、使用方法を示すことを意図したものであるため、同等の順次的な LINQ to Objects クエリほど高速ではない可能性があります。 高速化の詳細については、「PLINQ での高速化について」を参照してください。 クエリに含まれる要素の順序を保持する方法の詳細については、「方法: PLINQ クエリの順序を制御する」を参照してください。

関連項目