Прочитать на английском

Поделиться через


Как контролировать упорядочивание в запросе PLINQ

В этих примерах показано, как управлять упорядочением в запросе PLINQ с помощью метода расширения AsOrdered.

Предупреждение

Эти примеры предназначены в первую очередь для демонстрации использования и могут как выполняться быстрее, так и медленнее, чем эквивалентные последовательные запросы LINQ to Objects.

Пример 1

В следующем примере сохраняется порядок исходной последовательности. Иногда это необходимо; Например, для некоторых операторов запросов требуется упорядоченная исходная последовательность для получения правильных результатов.

C#
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 item in parallelQuery)
{
    Console.Write($"{item} ");
}

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

Пример 2

В следующем примере показаны некоторые операторы запросов, исходная последовательность которых, вероятно, будет упорядочена. Эти операторы будут работать над неупорядоченными последовательностями, но они могут привести к неожиданным результатам.

C#
// 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: {cust.CustomerID}");
}

Чтобы запустить этот метод, вставьте его в класс PLINQDataSample в проект PLINQ Data Sample и нажмите клавишу F5.

Пример 3

В следующем примере показано, как сохранить порядок для первой части запроса, а затем удалить порядок для повышения производительности предложения соединения, а затем повторно применить порядок к конечной последовательности результатов.

C#
// 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($"{v.ID} {v.Customer} {v.Product}");
}

Чтобы запустить этот метод, вставьте его в класс PLINQDataSample в проект PLINQ Data Sample и нажмите клавишу F5.

См. также