los programación de computadoras El término "hilo" es la abreviatura de hilo de ejecución, en el que un procesador sigue una ruta específica a través de su código. El concepto de seguir más de un hilo a la vez introduce el tema de multitarea y multihilo.
Una aplicación tiene uno o más procesos en ella. Piense en un proceso como un programa que se ejecuta en su computadora. Ahora cada proceso tiene uno o más hilos. Una aplicación de juego puede tener un hilo para cargar recursos desde el disco, otra para hacer IA y otra para ejecutar el juego como servidor.
En .NET / Windows, el sistema operativo asigna el tiempo del procesador a un subproceso. Cada hilo realiza un seguimiento de los controladores de excepciones y la prioridad en la que se ejecuta, y tiene un lugar para guardar el contexto del hilo hasta que se ejecute. El contexto del hilo es la información que el hilo necesita reanudar.
Multitarea con hilos
Los subprocesos ocupan un poco de memoria y crearlos lleva un poco de tiempo, por lo que, por lo general, no desea utilizar muchos. Recuerde, compiten por el tiempo de procesador. Si su computadora tiene varias CPU, Windows o .NET pueden ejecutar cada subproceso en una CPU diferente, pero si varios subprocesos se ejecutan en la misma CPU, entonces solo uno puede estar activo a la vez y cambiar los subprocesos toma hora.
La CPU ejecuta un subproceso por unos pocos millones de instrucciones y luego cambia a otro subproceso. Todos los registros de la CPU, el punto de ejecución del programa actual y la pila deben guardarse en algún lugar para el primer subproceso y luego restaurarse desde otro lugar para el siguiente subproceso.
Crear un hilo
En el espacio de nombres Sistema. Enhebrar, encontrarás el tipo de hilo. El hilo constructor (ThreadStart) crea una instancia de un hilo. Sin embargo, en reciente C# código, es más probable que pase una expresión lambda que llame al método con cualquier parámetro.
Si no estás seguro de expresiones lambda, puede valer la pena echarle un vistazo a LINQ.
Aquí hay un ejemplo de un hilo que se crea y se inicia:
utilizando el sistema;
utilizando el sistema. Enhebrar;
espacio de nombres ex1
{
Programa de clase
{
público estático vacío Write1 ()
{
Consola. Escribir ('1');
Hilo. Sueño (500);
}
vacío estático Main (string [] args)
{
var task = nuevo hilo (Write1);
tarea. Comienzo() ;
para (var i = 0; i <10; i ++)
{
Consola. Escribir ('0');
Consola. Escribir (tarea. IsAlive? 'A': 'D');
Hilo. Sueño (150);
}
Consola. Leer la clave() ;
}
}
}
Todo lo que hace este ejemplo es escribir "1" en la consola. El hilo principal escribe un "0" en la consola 10 veces, cada vez seguido de una "A" o "D" dependiendo de si el otro hilo sigue vivo o muerto.
El otro hilo solo se ejecuta una vez y escribe un "1". Después de la demora de medio segundo en el hilo Write1 (), el hilo termina y la tarea. IsAlive en el bucle principal ahora devuelve "D"
Grupo de subprocesos y biblioteca paralela de tareas
En lugar de crear su propio hilo, a menos que realmente necesite hacerlo, utilice un conjunto de hilos. Desde .NET 4.0, tenemos acceso a la Biblioteca Paralela de Tareas (TPL). Como en el ejemplo anterior, nuevamente necesitamos un poco de LINQ, y sí, son todas expresiones lambda.
Tasks usa el Grupo de hilos detrás de escena, pero aproveche mejor los hilos dependiendo del número en uso.
El objeto principal en el TPL es una tarea. Esta es una clase que representa una operación asincrónica. La forma más común de comenzar a ejecutar las cosas es con la tarea. Fábrica. InicioNuevo como en:
Tarea. Fábrica. StartNew (() => DoSomething ());
Donde DoSomething () es el método que se ejecuta. Es posible crear una tarea y no ejecutarla de inmediato. En ese caso, simplemente use Tarea de esta manera:
var t = nueva tarea (() => consola. WriteLine ("Hola"));
...
t. Comienzo();
Eso no inicia el hilo hasta que se llama a .Start (). En el siguiente ejemplo, son cinco tareas.
utilizando el sistema;
utilizando el sistema. Enhebrar;
utilizando el sistema. Enhebrado Tareas;
espacio de nombres ex1
{
Programa de clase
{
público estático vacío Write1 (int i)
{
Consola. Escribe (i);
Hilo. Sueño (50);
}
vacío estático Main (string [] args)
{
para (var i = 0; i <5; i ++)
{
valor var = i;
var runningTask = Tarea. Fábrica. StartNew (() => Write1 (value));
}
Consola. Leer la clave() ;
}
}
}
Ejecute eso y obtendrá los dígitos del 0 al 4 en un orden aleatorio como 03214. Esto se debe a que .NET determina el orden de ejecución de la tarea.
Tal vez se pregunte por qué se necesita el valor var = i. Intente eliminarlo y llamar Escribir (i), y verá algo inesperado como 55555. ¿Por qué es esto? Es porque la tarea muestra el valor de i en el momento en que se ejecuta la tarea, no cuando se creó la tarea. Al crear un nuevo variable Cada vez en el ciclo, cada uno de los cinco valores se almacena y recoge correctamente.