c# - threads - parallel foreach try catch
Parallels.ForEach Tomando el mismo tiempo que Foreach (2)
Al ver lo que está haciendo, el único momento en que sus hilos no están haciendo nada es cuando el sistema operativo los desconecta para darle otro hilo, por lo que tiene la ventaja de poder ejecutar en otro núcleo: el costo de todos los cambios de contexto.
Tendrías que iniciar sesión para averiguarlo, pero sospecho que el cuello de la botella es un hilo físico, a menos que tengas uno en otro lugar que no hayas publicado.
Si eso es cierto, me sentiría tentado a cambiar el código. Tiene dos hilos uno para encontrar propiedades para comparar, y uno para compararlas y una cola común. Puede ser otro para lanzar clases en la lista y cotejar los resultados.
Sin embargo, podría ser mi cabeza de procesamiento por lotes.
Todas,
Estoy usando Parallels.ForEach de la siguiente manera
private void fillEventDifferencesParallels(IProducerConsumerCollection<IEvent> events, Dictionary<string, IEvent> originalEvents)
{
Parallel.ForEach<IEvent>(events, evt =>
{
IEvent originalEventInfo = originalEvents[evt.EventID];
evt.FillDifferences(originalEventInfo);
});
}
Ok, entonces el problema que tengo es que tengo una lista de 28 de estos (una muestra de prueba, esto debería poder escalar a más de 200) y el método de FillDifferences es bastante lento (aproximadamente 4s por llamada). Por lo tanto, el tiempo promedio para que esto se ejecute en un ForEach normal ha sido de alrededor de 100-130 segundos. Cuando ejecuto lo mismo en paralelo, toma la misma cantidad de tiempo y activa mi CPU (Intel I5, 2 núcleos, 2 subprocesos por núcleo) haciendo que la aplicación se vuelva lenta mientras se está ejecutando esta consulta (esto se está ejecutando en un hilo eso fue generado por el hilo GUI).
Entonces mi pregunta es, ¿qué estoy haciendo mal que está causando que esto tome la misma cantidad de tiempo? Leí que List no era seguro para subprocesos, así que reescribí esto para usar IProducerConsumerCollection. ¿Hay otras trampas que puedan estar causando esto?
El método FillDifferences llama a una clase estática que usa la reflexión para descubrir cuántas diferencias hay entre el objeto original y modificado. El objeto estático no tiene variables ''globales'', solo las locales a los métodos que se invocan.
Algunos de ustedes querían ver lo que llamaba el método FillDifferences (). Aquí es donde termina en última instancia:
public List<IDifferences> ShallowCompare(object orig, object changed, string currentName)
{
List<IDifferences> differences = new List<IDifferences>();
foreach (MemberInfo m in orig.GetType().GetMembers())
{
List<IDifferences> temp = null;
//Go through all MemberInfos until you find one that is a Property.
if (m.MemberType == MemberTypes.Property)
{
PropertyInfo p = (PropertyInfo)m;
string newCurrentName = "";
if (currentName != null && currentName.Length > 0)
{
newCurrentName = currentName + ".";
}
newCurrentName += p.Name;
object propertyOrig = null;
object propertyChanged = null;
//Find the property Information from the orig object
if (orig != null)
{
propertyOrig = p.GetValue(orig, null);
}
//Find the property Information from the changed object
if (changed != null)
{
propertyChanged = p.GetValue(changed, null);
}
//Send the property to find the differences, if any. This is a SHALLOW compare.
temp = objectComparator(p, propertyOrig, propertyChanged, true, newCurrentName);
}
if (temp != null && temp.Count > 0)
{
foreach (IDifferences difference in temp)
{
addDifferenceToList(differences, difference);
}
}
}
return differences;
}
Creo que es posible que te encuentres con el costo del cambio de contexto del hilo. Dado que estas tareas son de larga duración, puedo imaginar que se están creando muchos hilos en ThreadPool para manejarlas.
- 0ms == 1 hilo
- 500ms == 2 hilos
- 1000 ms == 3 hilos
- 1500 ms == 4 hilos
- 2000 ms == 5 hilos
- 2500 ms == 6 hilos
- 3000 ms == 7 hilos
- 3500 ms == 8 hilos
- 4000 ms == 9 hilos
En 4000 ms, solo se completó la primera tarea, por lo que este proceso continuará. Una posible solución es la siguiente.
System.Threading.ThreadPool.SetMaxThreads(4, 4);