🅿️PLINQ

PLINQ (Parallel LINQ) es parte del TPL (Task Parallel Library) en .NET, permite que tu código ejecute consultas sobre colecciones de datos en paralelo, es decir, utilizando múltiples hilos o procesadores a la vez para realizar la tarea más rápidamente.

https://www.bytehide.com/blog/linq-performance-optimization-csharp

🛠 Cómo Usar PLINQ

1. Convertir a Paralelo

Usar

el método AsParallel() para convertir una colección enumerable en una versión que pueda ser procesada en paralelo.

var myCollection = Enumerable.Range(1, 100);
var parallelQuery = myCollection.AsParallel().Where(x => x % 2 == 0);

Este ejemplo filtra los números pares de una colección de enteros del 1 al 100, utilizando procesamiento en paralelo.

2. Ejecución Forzada

A diferencia de las consultas LINQ regulares que se ejecutan de inmediato, las consultas PLINQ esperan hasta que realmente necesitas los resultados para ejecutarse.

Las consultas PLINQ son diferidas, por lo que necesitas forzar su ejecución para obtener resultados. Esto se puede hacer con métodos como ToList(), ToArray(), o un bucle foreach:.

var resultList = parallelQuery.ToList();

Este código fuerza la ejecución de la consulta PLINQ anterior, materializando el resultado en una lista.

3. Ordenamiento

Cuando usas PLINQ, el orden en que se procesan los datos puede cambiar debido a que se están manejando en paralelo. Si el orden de los resultados es importante, como seguir la secuencia de una lista de tareas, usarías AsOrdered() para mantenerlo. Si el orden no importa, como en una lista de compras donde solo importa que no olvides nada, usamos AsUnordered() para permitir que PLINQ optimice cómo maneja las tareas, potencialmente haciéndolo aún más rápido.

Controlar el orden de los resultados con AsOrdered() para mantener el orden original o AsUnordered() para permitir que el sistema optimice el procesamiento sin mantener el orden:

var orderedParallelQuery = myCollection.AsParallel().AsOrdered().Where(x => x % 2 == 0);

Este código mantiene el orden de los elementos mientras filtra los números pares.

4. Limitar Paralelismo

Limitar el paralelismo te permite controlar cuántos hilos o procesadores se utilizan para la tarea, lo que puede ser útil si quieres asegurarte de que otras tareas o aplicaciones en tu computadora también tengan recursos para funcionar bien.

var limitedParallelQuery = myCollection.AsParallel().WithDegreeOfParallelism(2).Where(x => x % 2 == 0);

Este ejemplo limita el procesamiento paralelo a usar máximo 2 núcleos.

5. Excepciones

Trabajar en paralelo puede complicar el manejo de errores.

AggregateException es una manera de recopilar y manejar múltiples errores que pueden ocurrir durante la ejecución de tus consultas PLINQ, permitiéndote lidiar con ellos de manera eficiente.

try
{
    var result = myCollection.AsParallel().Where(x => ThrowException(x)).ToList();
}
catch (AggregateException ae)
{
    ae.Handle(e =>
    {
        if (e is InvalidOperationException)
        {
            Console.WriteLine("Caught an invalid operation exception.");
            return true;
        }
        return false;
    });
}

Este código intenta ejecutar una consulta que puede lanzar una excepción específica, y la maneja adecuadamente.

var numeros = Enumerable.Range(1, 20); 

try
{
    var resultado = numeros
        .AsParallel()
        .Select(n => ProcesarNumero(n))
        .ToList(); // Forzamos la ejecución para capturar las excepciones
}
catch (AggregateException ae)
{
    Console.WriteLine($"Se encontraron {ae.InnerExceptions.Count} excepciones.");

    foreach (var e in ae.InnerExceptions)
    {
        switch (e)
        {
            case InvalidOperationException ioe:
                Console.WriteLine($"Operación inválida: {ioe.Message}");
                break;
            case ArgumentException ae:
                Console.WriteLine($"Argumento inválido: {ae.Message}");
                break;
            default:
                Console.WriteLine($"Excepción no esperada: {e.Message}");
                throw; // Re-lanzamos las excepciones que no sepamos cómo manejar
        }
    }
}

Última actualización