Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

88
Vistas
Las operaciones anidadas paralelas devuelven resultados extraños

Estoy tratando de usar la biblioteca Parallel para mi código y me enfrento a un problema extraño. Hice un programa corto para demostrar el comportamiento. En resumen, hago 2 bucles (uno dentro de otro). El primer ciclo genera una matriz aleatoria de 200 enteros y el segundo ciclo agrega todas las matrices en una lista grande. El problema es que, al final, no obtengo un múltiplo de 200 enteros, sino que veo que algunas ejecuciones no esperan a que la matriz aleatoria se cargue por completo. Es difícil de explicar, así que aquí el código de muestra:

 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace TestParallel { class Program { static int RecommendedDegreesOfParallelism = 8; static int DefaultMaxPageSize = 200; static void Main(string[] args) { int maxPage = 50; List<int> lstData = new List<int>(); Parallel.For(0, RecommendedDegreesOfParallelism, new ParallelOptions() { MaxDegreeOfParallelism = RecommendedDegreesOfParallelism }, (index) => { int cptItems = 0; int cptPage = 1 - RecommendedDegreesOfParallelism + index; int idx = index; do { cptPage += RecommendedDegreesOfParallelism; if (cptPage > maxPage) break; int Min = 0; int Max = 20; Random randNum = new Random(); int[] test2 = Enumerable .Repeat(0, DefaultMaxPageSize) .Select(i => randNum.Next(Min, Max)) .ToArray(); var lstItems = new List<int>(); lstItems.AddRange(test2); var lstRes = new List<int>(); lstItems.AsParallel().WithDegreeOfParallelism(8).ForAll((item) => { lstRes.Add(item); }); Console.WriteLine($"{Task.CurrentId} = {lstRes.Count}"); lstData.AddRange(lstRes); cptItems = lstRes.Count; } while (cptItems == DefaultMaxPageSize); } ); Console.WriteLine($"END: {lstData.Count}"); Console.ReadKey(); } } }

Y aquí hay un registro de ejecución:

 4 = 200 1 = 200 2 = 200 3 = 200 6 = 200 5 = 200 7 = 200 8 = 200 1 = 200 6 = 194 2 = 191 5 = 200 7 = 200 8 = 200 4 = 200 5 = 200 3 = 182 4 = 176 8 = 150 7 = 200 5 = 147 1 = 200 7 = 189 1 = 200 1 = 198 END: 4827

Podemos ver que algunos bucles devuelven menos de 200 elementos. ¿Como es posible?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Esto aquí no es seguro para subprocesos:

 lstItems.AsParallel().WithDegreeOfParallelism(8).ForAll((item) => { lstRes.Add(item); });

De la documentación para List<T> :

Es seguro realizar varias operaciones de lectura en una lista, pero pueden surgir problemas si se modifica la colección mientras se lee. Para garantizar la seguridad de los subprocesos, bloquee la colección durante una operación de lectura o escritura. Para habilitar el acceso a una colección por múltiples subprocesos para lectura y escritura, debe implementar su propia sincronización.

No lo menciona explícitamente, pero .Add() también puede fallar cuando varios subprocesos lo llaman simultáneamente.

La solución sería bloquear las llamadas a List<T>.Add() en el ciclo anterior, pero si lo hace, es probable que sea más lento que simplemente agregar los elementos en un ciclo en un solo hilo.

 var locker = new object(); lstItems.AsParallel().WithDegreeOfParallelism(8).ForAll((item) => { lock (locker) { lstRes.Add(item); } });
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda