Compartir vía


Programación de subprocesos

Cada subproceso tiene una prioridad de subproceso asignada a él. A los subprocesos creados en Common Language Runtime se les asigna inicialmente la prioridad de ThreadPriority.Normal. Los subprocesos creados fuera del tiempo de ejecución mantienen la prioridad que tenían antes de entrar en el entorno administrado. Puede obtener o establecer la prioridad de cualquier subproceso con la propiedad Thread.Priority.

Los subprocesos están programados para ejecutarse según su prioridad. Aunque los subprocesos se ejecutan durante el tiempo de ejecución, el sistema operativo asigna intervalos de tiempo de procesador a todos los subprocesos. Los detalles del algoritmo de programación utilizado para determinar el orden en que se ejecutan los subprocesos varían en función de cada sistema operativo. En algunos sistemas operativos, el subproceso con la prioridad más alta (de entre los subprocesos que se pueden ejecutar) está programado siempre para que se ejecute primero. Si hay disponibles varios subprocesos con la misma prioridad, el programador recorre los subprocesos con dicha prioridad, dando a cada subproceso un intervalo de tiempo fijo para su ejecución. Siempre que un subproceso con una prioridad más alta esté disponible para su ejecución, los subprocesos con menor prioridad no se llegan a ejecutar. Si no hay más subprocesos ejecutables con una prioridad determinada, el programador pasa a la siguiente prioridad más baja y programa la ejecución de los subprocesos que tienen esa prioridad. Si un subproceso de prioridad superior se convierte en ejecutable, se relega el subproceso de menor prioridad y el subproceso con mayor prioridad se puede ejecutar una vez más. Sobre todo, el sistema operativo también puede ajustar las prioridades de los subprocesos de forma dinámica como una interfaz de usuario de la aplicación se mueve entre el primer y segundo plano. Otros sistemas operativos puede optar por utilizar un algoritmo de programación diferente.

Ejemplo

Este es un ejemplo de la ejecución de 9 subprocesos en todos los cinco niveles de prioridad de la enumeración Thread.Priority, donde los últimos 5 están en el nivel de prioridad más alto. Además, tenemos compatibilidad con la devolución de llamada del artículo anterior, que en este contexto demuestra que el orden de inicialización y priorización de subprocesos podría no reflejarse siempre en el código posterior ni en el orden de inicio de las ejecuciones de procesos. Es decir, se ve aquí la naturaleza paralela de la ejecución del código y la demostración de los segmentos de tiempo de procesador asignados por el sistema operativo para cada subproceso. Esto resalta la influencia y el control del entorno en el que se ejecutan los subprocesos. Dicho esto, ciertamente vemos que los subprocesos de prioridad más alta reciben realmente prioridad en la ejecución.

El código siguiente generará resultados arbitrarios en cada ejecución. Sin embargo, se podrían observar patrones de secuencia comunes de prioridades que se ejecutan después de ejecutar el código varias veces y analizar las salidas.

namespace snippets;

public class SchedulingThreads
{
    public void RunMultipleThreadsOnDifferentPriorities()
    {
        var threadsList = new List<Thread>(9);

        // Initialize 9 threads. 5 with Highest priority, and the first 4 from Lowest to Normal range.
        for (int i = 0; i < 9; i++)
        {
            var thread = new Thread(() => { new ThreadWithCallback(Callback).Process(); });

            if (i > 3)
                thread.Priority = ThreadPriority.Highest;
            else
                thread.Priority = (ThreadPriority)i;

            threadsList.Add(thread);
        }

        threadsList.ForEach(thread => thread.Start());
    }

    public void Callback(ThreadPriority threadPriority)
    {
        Console.WriteLine($"Callback in {threadPriority} priority. \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");
    }

    public class ThreadWithCallback
    {
        public ThreadWithCallback(Action<ThreadPriority> callback)
        {
            this.callback = callback;
        }

        public Action<ThreadPriority> callback;

        public void Process()
        {
            Console.WriteLine($"Entered process in {Thread.CurrentThread.Priority} priority.  \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");
            Thread.Sleep(1000);
            Console.WriteLine($"Finished process in {Thread.CurrentThread.Priority} priority. \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");

            if (callback != null)
            {
                callback(Thread.CurrentThread.Priority);
            }
        }
    }

    // The example displays the output like the following:
    //      Entered process in Highest priority.             ThreadId: 9.
    //      Entered process in Highest priority.             ThreadId: 12.
    //      Entered process in Normal priority.              ThreadId: 6.
    //      Entered process in BelowNormal priority.         ThreadId: 5.
    //      Entered process in Lowest priority.              ThreadId: 4.
    //      Entered process in AboveNormal priority.         ThreadId: 7.
    //      Entered process in Highest priority.             ThreadId: 11.
    //      Entered process in Highest priority.             ThreadId: 10.
    //      Entered process in Highest priority.             ThreadId: 8.
    //      Finished process in Highest priority.            ThreadId: 9.
    //      Finished process in Highest priority.            ThreadId: 12.
    //      Finished process in Highest priority.            ThreadId: 8.
    //      Finished process in Highest priority.            ThreadId: 10.
    //      Callback in Highest priority.                    ThreadId: 10.
    //      Finished process in AboveNormal priority.        ThreadId: 7.
    //      Callback in AboveNormal priority.                ThreadId: 7.
    //      Finished process in Lowest priority.             ThreadId: 4.
    //      Callback in Lowest priority.                     ThreadId: 4.
    //      Finished process in Normal priority.             ThreadId: 6.
    //      Callback in Highest priority.                    ThreadId: 9.
    //      Callback in Highest priority.                    ThreadId: 8.
    //      Callback in Highest priority.                    ThreadId: 12.
    //      Finished process in Highest priority.            ThreadId: 11.
    //      Callback in Highest priority.                    ThreadId: 11.
    //      Callback in Normal priority.                     ThreadId: 6.
    //      Finished process in BelowNormal priority.        ThreadId: 5.
    //      Callback in BelowNormal priority.                ThreadId: 5.
}

Consulte también