c# - segundo - kaspersky alenta mi pc
MĂșltiples tareas se ralentiza (3)
¿Por qué puede comenzar las 3 primeras tareas de forma correcta, pero luego se requieren 5-10 segundos para que la tarea 4 se inicie, y después de que la tarea 4 haya comenzado, se necesitan 5-10 segundos antes de que comience la tarea 5 y así sucesivamente. ¿Es el GC que está haciendo algo? ¿Podría alguien aclarar qué está pasando?
De forma predeterminada, la primera vez que ejecuta esto, ThreadPool
se asigna utilizando el número mínimo de subprocesos de trabajo. Después de que se programen las primeras 4 tareas, la agrupación de hilos se "acelerará" para manejar más a lo largo del tiempo, por lo que se ve la demora.
En mi sistema (que tiene 8 núcleos), los primeros 8 son instantáneos, luego los dos siguientes se inician un segundo después.
En su caso, si ejecuta su prueba dos veces, la segunda vez, todos los hilos se iniciarán de inmediato. Esto se debe a que, después de la primera ejecución, ThreadPool debería tener suficientes trabajadores para programar esto de inmediato.
Intente lo siguiente para ver este comportamiento en acción. Si deja la llamada SetMinThreads en su lugar, todos estos se programarán de inmediato. Si lo comenta, verá que, la primera vez, toma un tiempo, pero la segunda vez (siempre que espere a que se completen los hilos), los hilos se ejecutarán de inmediato.
static void DoIt(string name)
{
Console.WriteLine("Hello {0} | {1} - {2}", name, Thread.CurrentThread.ManagedThreadId, DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("Bye {0} | {1} - {2}", name, Thread.CurrentThread.ManagedThreadId, DateTime.Now);
}
static void Main()
{
int workerThreads, complete;
ThreadPool.GetMinThreads(out workerThreads, out complete);
Console.WriteLine(workerThreads);
// Comment out this line to see the difference...
// WIth this commented out, the second iteration will be immediate
ThreadPool.SetMinThreads(100, complete);
Action run = () =>
{
for (int i = 0; i < 20; ++i)
{
int tmp = i;
Task.Factory.StartNew(() => DoIt(tmp.ToString()));
}
};
run();
Console.WriteLine("Press a key to run again...");
Console.ReadKey();
run();
Console.WriteLine("Press a key to exit...");
Console.ReadKey();
}
Tenga en cuenta que este comportamiento en realidad tiene poco que ver con la TPL como un todo: es más el TaskScheduler
predeterminado que se usa y que pasa las tareas a ThreadPool
. Si LongRunning
que configurar estos subprocesos con la sugerencia LongRunning
en su llamada a StartNew()
, por ejemplo, todos comenzarían inmediatamente (ya que el programador predeterminado configurará un nuevo subproceso dedicado y lo ejecutará inmediatamente).
El código:
static void DoIt(string name)
{
Console.WriteLine("Hello {0} | {1}", name, Thread.CurrentThread.ManagedThreadID);
Thread.Sleep(5000);
Console.WriteLine("Bye {0} | {1}", name, Thread.CurrentThread.ManagedThreadID);
}
static void Main()
{
Task.Factory.StartNew(() => DoIt("One"));
Task.Factory.StartNew(() => DoIt("Two"));
Task.Factory.StartNew(() => DoIt("Three"));
Task.Factory.StartNew(() => DoIt("Four"));
Task.Factory.StartNew(() => DoIt("Five"));
Task.Factory.StartNew(() => DoIt("Six"));
Task.Factory.StartNew(() => DoIt("Seven"));
Task.Factory.StartNew(() => DoIt("Eight"));
Task.Factory.StartNew(() => DoIt("Nine"));
Task.Factory.StartNew(() => DoIt("Ten"));
Console.ReadKey();
}
¿Por qué puede comenzar las 3 primeras tareas de forma correcta, pero luego se requieren 5-10 segundos para que la tarea 4 se inicie, y después de que la tarea 4 haya comenzado, se necesitan 5-10 segundos antes de que comience la tarea 5 y así sucesivamente. ¿Es el GC que está haciendo algo? ¿Podría alguien aclarar qué está pasando?
El TPL contiene algoritmos muy sofisticados que se adaptan a la carga de trabajo. Lo que está experimentando suena bien para una máquina de 4 núcleos: el TPL ha decidido hacer algo que cree que es beneficioso en una situación en la que se crean tantos subprocesos.
Las tareas no se están ralentizando, están siendo puestas en cola por la biblioteca paralela de tareas. El CLR sabe cuántos núcleos lógicos están disponibles en su computadora; El grupo de subprocesos TPL utiliza esta información para determinar cuántos subprocesos de trabajo hay que hacer disponibles. En tu caso, probablemente tengas cuatro núcleos lógicos; quitando uno para el subproceso principal (en el que se está ejecutando Main()
) quedan tres núcleos (y tres trabajadores del grupo de subprocesos) para ejecutar las tareas.