Gewusst wie: Steuern der Sortierung in einer PLINQ-Abfrage

In diesen Beispielen wird gezeigt, wie Sie die Sortierung in einer PLINQ-Abfrage mithilfe der AsOrdered-Erweiterungsmethode steuern.

WarnhinweisVorsicht

Diese Beispiele sollen in erster Linie die Verwendung veranschaulichen, und sie werden eventuell nicht schneller als die entsprechenden sequenziellen LINQ to Objects-Abfragen ausgeführt.

Beispiel

Im folgenden Beispiel wird die Reihenfolge der Quellsequenz beibehalten. Dies ist in bestimmten Fällen notwendig. Einige Abfrageoperatoren erfordern beispielsweise eine geordnete Quellsequenz, um korrekte Ergebnisse zu liefern.

Sub OrderedQuery()

    Dim source = Enumerable.Range(9, 10000)

    ' Source is ordered let's preserve it.
    Dim parallelQuery = From num In source.AsParallel().AsOrdered()
                            Where num Mod 3 = 0
                            Select num

    ' Use For Each to preserve order at execution time.
    For Each item In parallelQuery
        Console.Write("{0} ", item)
    Next

    ' Some operators expect an ordered source sequence.
    Dim lowValues = parallelQuery.Take(10)

End Sub
var source = Enumerable.Range(9, 10000);

// Source is ordered; let's preserve it.
var parallelQuery = from num in source.AsParallel().AsOrdered()
                    where num % 3 == 0
                    select num;

// Use foreach to preserve order at execution time.
foreach (var v in parallelQuery)
    Console.Write("{0} ", v);

// Some operators expect an ordered source sequence.
var lowValues = parallelQuery.Take(10);

Im folgenden Beispiel werden einige Abfrageoperatoren dargestellt, bei denen mit großer Wahrscheinlichkeit eine geordnete Quellsequenz erwartet wird. Diese Operatoren können zwar auch für ungeordnete Sequenzen verwendet werden, sie haben dort jedoch ggf. unerwartete Ergebnisse zur Folge.

' Paste into PLINQDataSample class
Shared Sub SimpleOrdering()
    Dim customers As List(Of Customer) = GetCustomers().ToList()

    ' Take the first 20, preserving the original order

    Dim firstTwentyCustomers = customers _
                                .AsParallel() _
                                .AsOrdered() _
                                .Take(20)

    Console.WriteLine("Take the first 20 in original order")
    For Each c As Customer In firstTwentyCustomers
        Console.Write(c.CustomerID & " ")
    Next

    ' All elements in reverse order.
    Dim reverseOrder = customers _
                        .AsParallel() _
                        .AsOrdered() _
                        .Reverse()

    Console.WriteLine(vbCrLf & "Take all elements in reverse order")
    For Each c As Customer In reverseOrder
        Console.Write("{0} ", c.CustomerID)
    Next
    ' Get the element at a specified index. 
    Dim cust = customers.AsParallel() _
                        .AsOrdered() _
                        .ElementAt(48)

    Console.WriteLine("Element #48 is: " & cust.CustomerID)

End Sub
// Paste into PLINQDataSample class.
static void SimpleOrdering()
{

    var customers = GetCustomers();

    // Take the first 20, preserving the original order
    var firstTwentyCustomers = customers
                                .AsParallel()
                                .AsOrdered()
                                .Take(20);

    foreach (var c in firstTwentyCustomers)
        Console.Write("{0} ", c.CustomerID);

    // All elements in reverse order.
    var reverseOrder = customers
                        .AsParallel()
                        .AsOrdered()
                        .Reverse();

    foreach (var v in reverseOrder)
        Console.Write("{0} ", v.CustomerID);

    // Get the element at a specified index. 
    var cust = customers.AsParallel()
                        .AsOrdered()
                        .ElementAt(48);

    Console.WriteLine("Element #48 is: {0}", cust.CustomerID);

}

Fügen Sie diese Methode in die PLINQDataSample-Klasse des Projekts PLINQ-Datenbeispiel ein, und drücken Sie F5, um sie auszuführen.

Im folgenden Beispiel wird gezeigt, wie Sie die Reihenfolge für den ersten Teil einer Abfrage beibehalten, die Sortierung anschließend entfernen, um die Leistung einer Join-Klausel zu erhöhen, und dann die Endergebnissequenz erneut sortieren.

' Paste into PLINQDataSample class
Sub OrderedThenUnordered()
    Dim Orders As IEnumerable(Of Order) = GetOrders()
    Dim orderDetails As IEnumerable(Of OrderDetail) = GetOrderDetails()

    ' Sometimes it's easier to create a query
    ' by composing two subqueries
    Dim query1 = From ord In Orders.AsParallel()
             Where ord.OrderDate < DateTime.Parse("07/04/1997")
             Select ord
             Order By ord.CustomerID
             Take 20

    Dim query2 = From ord In query1.AsUnordered()
             Join od In orderDetails.AsParallel() On ord.OrderID Equals od.OrderID
            Order By od.ProductID
            Select New With {ord.OrderID, ord.CustomerID, od.ProductID}


    For Each item In query2
        Console.WriteLine("{0} {1} {2}", item.OrderID, item.CustomerID, item.ProductID)
    Next
End Sub
// Paste into PLINQDataSample class.
static void OrderedThenUnordered()
{

    var orders = GetOrders();
    var orderDetails = GetOrderDetails();

    var q2 = orders.AsParallel()
       .Where(o => o.OrderDate < DateTime.Parse("07/04/1997"))
       .Select(o => o)
       .OrderBy(o => o.CustomerID) // Preserve original ordering for Take operation.
       .Take(20)
       .AsUnordered()  // Remove ordering constraint to make join faster.
       .Join(
              orderDetails.AsParallel(),
              ord => ord.OrderID,
              od => od.OrderID,
              (ord, od) =>
              new
              {
                  ID = ord.OrderID,
                  Customer = ord.CustomerID,
                  Product = od.ProductID
              }
             )
       .OrderBy(i => i.Product); // Apply new ordering to final result sequence.

    foreach (var v in q2)
        Console.WriteLine("{0} {1} {2}", v.ID, v.Customer, v.Product);

}

Fügen Sie diese Methode in die PLINQDataSample-Klasse des Projekts PLINQ-Datenbeispiel ein, und drücken Sie F5, um sie auszuführen.

Siehe auch

Referenz

ParallelEnumerable

Konzepte

Paralleles LINQ (PLINQ)