Si no estás familiarizado con profundos conocimientos de programacíón, tal vez tengas la idea de la ejecución secuencial del código fuente de un programa, es decir, que las líneas de código fuente se van ejecutando de una manera lineal de principio a fin, aunque realmente esto no sea así pues la compilación del código fuente en el entorno .NET es algo más complicada que eso.
Sin embargo, y teniendo en cuenta el funcionamiento de la compilación de .NET, es el momento de que comiences a pensar en algo más que la idea de ejecición secuencial del código fuente. Mediante la programación multi-hilo es posible que la ejecución del código fuente vaya por dos o más puntos diferentes, independientes entre sí, además de una línea secuencial de ejecución primaria. De esta forma, es posible la realización de diferentes tareas en un mismo tiempo, consiguiendo de esta manera una optimización de los tiempos de trabajo de la CPU. Sin embargo, esto no quiere decir que la CPU trabaje en varias tareas al mismo tiempo, pues no tiene capacidad para ello. En su lugar, la CPU asigna a cada tarea diferentes tiempos de ejecución en función de su importancia, facilitando así el uso del desarrollo asíncrono.
Un ejemplo de ello sería una aplicación cualquiera que tuviera una visualización de formularios que serían controlados por el hilo principal de ejecución, pero que conforme el usuario trabaje en estos formularios, la aplicación deba guardar los datos introducidos en, por ejemplo, unas bases de datos. Las operaciones sobre las bases de datos podrán ser cedidas a otros hilos, de manera que si estas operaciones requieren tiempos amplios para su ejecución, el usuario no notará interrupciones en la ejecución del hilo principal y podrá seguir haciendo uso normal de la aplicación sin darse cuenta de las complejas operaciones que se estén desarrollando en segundo plano.
Para el desarrollo de tareas multi-hilo se hace uso del espacio de nombres 'System.Threading', el cual alberga clases que permiten crear y conrtolar tareas, principalmente mediante la clase 'Thread'.
Creación de un hilo.
Para la creación de un hilo se hace uso del delegado 'ThreadStart', que tomará como argumento de su constructor el nombre del método que será ejecutado por el nuevo hilo, y este delegado se pasará a continuación como argumento del constructor del objeto 'Thread'. Finalmente llamaremos al método 'Start' del objeto 'Thread' para iniciar la llamada al métod del delegado 'ThreadStart':
Vemos ahora un ejemplo de lo anterior dentro de una aplicación de consola:
Si compilas y ejecutas la aplicación, observarás que la salida por la consola muestra las cadenas de texto de inicio del hilo principal, fin del hilo principal, inicio del hilo secundario y fin del hilo secundario, exactamente por ese orden. De esto se deduce que tras inicial el hilo principal de la aplicación, se hace la llamada al hilo secundario y éste se ejecuta hasta su fin independientemente de que el hilo principal haya finalizado, de manera asíncrona e independiente. Puedes experimentar con esta aplicación sacando por la consola el valor de la propiedad estática 'CurrentThread' del objeto de la clase 'Thread' creado y comprobarás que ésta no tiene el mismo valor según el médodo en ejecución en cada momento.
Suspender o anular un hilo.
Ahora no se te ocurrirá ningún ejemplo claro, pero cuando comiences a trabajar con hilos en tus aplicaciones, te dartás cuenta de que por alguna razón necesitas pausar un hilo cuando éste se está ejecutando. Esto se consigue de la siguiente manera tan simple:
Con esta sentencia lo que se consigue es pausar (o suspender) el hilo actual durante 5000 milisegundos, que es el valor que se ha pasado al constructor del método 'Sleep' de la clase 'Thread'.
Para abortar un hilo, es decir, para finalizar la ejecución de un hilo que se encuentra activo, se hace una llamada al método 'Abort':
Con esta sentencia finalizaremos el hilo secundario que habíamos creado anteriormente en la aplicación de consola. Es de mucha ayuda que este método lo podremos llamar desde el hilo principal o desde el método que ejecuta el hilo secundario.
Prioridad de los hilos.
De manera predeterminada, la prioridad de un hilo es normal, es decir, que todos los hilos creados se ejecutarán con la misma prioridad. Sin embargo, afortunadamente, C# nos permite cambiar estas condiciones mediante la propiedad 'Priority' de la clase 'Thread' con cualquiera de sus valores establecidos en la enumeración 'ThreadPriority': 'Highest', 'AboveNormal','Normal', 'BelowNormal' y 'Lowest'.