CreateThread en C#: Creación y Manejo de Hilos
El uso de hilos es fundamental en la programación de sistemas y aplicaciones que requieren realizar múltiples tareas simultáneamente. La función CreateThread
de kernel32.dll es una herramienta poderosa para crear hilos en aplicaciones de Windows. En este ejemplo, vamos a ver cómo podemos usar esta función en C# para crear un hilo y ejecutar código concurrentemente.
Descripción de CreateThread
CreateThread
La función CreateThread
se utiliza para crear un nuevo hilo en un programa. Su sintaxis en C (o C# mediante P/Invoke) es la siguiente:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // Atributos del hilo
DWORD dwStackSize, // Tamaño de la pila
LPTHREAD_START_ROUTINE lpStartAddress, // Dirección de la función que el hilo ejecutará
LPVOID lpParameter, // Parámetro que se pasa a la función
DWORD dwCreationFlags, // Flags de creación
LPDWORD lpThreadId // Identificador del hilo
);
Argumentos:
lpThreadAttributes
: Especifica un puntero a una estructura que define los atributos del hilo. Usualmente se pasaIntPtr.Zero
para usar los valores predeterminados.dwStackSize
: Es el tamaño de la pila para el nuevo hilo. Si se pasa 0, se utilizará el tamaño predeterminado.lpStartAddress
: Especifica la dirección de la función que será ejecutada por el hilo.lpParameter
: Puntero a los parámetros que se pasan a la función del hilo. Si no hay parámetros, se pasaIntPtr.Zero
.dwCreationFlags
: Especifica los flags de creación del hilo (0 para crear un hilo en ejecución).lpThreadId
: Devuelve el identificador del hilo creado.
Retorno:
Devuelve un handle para el hilo creado. Si la función falla, devuelve
IntPtr.Zero
.
Uso de CreateThread
en C#
CreateThread
en C#En C#, podemos utilizar P/Invoke para invocar funciones de la API nativa de Windows, como CreateThread
. A continuación, mostramos un ejemplo práctico en el que se crea un hilo utilizando CreateThread
y se ejecuta un método en ese hilo.
Código en C#:
using System; // Importar el espacio de nombres System.
using System.Runtime.InteropServices; // Importar el espacio de nombres InteropServices para usar DllImport.
using System.Threading; // Importar el espacio de nombres Threading para trabajar con hilos.
class Program
{
// Definir la firma del delegado que se utilizará para el método que se ejecutará en el hilo.
delegate void ThreadProcDelegate(IntPtr param);
// Importar la función CreateThread de la DLL kernel32.dll.
[DllImport("kernel32.dll")]
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, ThreadProcDelegate lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);
// Se llama a la función CreateThread para crear un nuevo hilo.
// Los parámetros son: lpThreadAttributes (IntPtr.Zero para usar los valores predeterminados),
// dwStackSize (0 para utilizar el tamaño de pila predeterminado),
// lpStartAddress (IntPtr.Zero para especificar que se ejecutará la función de inicio predeterminada),
// lpParameter (IntPtr.Zero para no pasar ningún parámetro al hilo),
// dwCreationFlags (0 para crear un hilo en ejecución),
// lpThreadId (el identificador del hilo creado).
static void Main()
{
// Crear un nuevo hilo con el método "MiMetodo" como delegado del hilo.
ThreadProcDelegate delegado = new ThreadProcDelegate(MiMetodo);
uint threadId;
CreateThread(IntPtr.Zero, 0, delegado, IntPtr.Zero, 0, out threadId);
// Llamada a CreateThread para crear el hilo. Esta función se ejecuta de forma asíncrona y retorna el identificador del hilo.
// Esperar a que el usuario presione una tecla antes de terminar la aplicación.
// Esto es necesario porque el hilo creado con CreateThread no impedirá que la aplicación termine.
Console.WriteLine("Presione una tecla para terminar...");
Console.ReadKey();
}
static void MiMetodo(IntPtr param)
{
// Este método se ejecutará en un hilo separado.
for (int i = 0; i < 5; i++)
{
// Imprimir el valor de "i" en la consola.
Console.WriteLine(i);
// Dormir el hilo durante un segundo.
Thread.Sleep(1000);
}
}
}
Explicación del Código:
Declaración del Delegado
ThreadProcDelegate
:Primero definimos un delegado (
ThreadProcDelegate
) que representa el tipo de método que se ejecutará en el hilo. Este delegado debe tener la misma firma que la función que se ejecutará en el hilo, en este caso,MiMetodo
.
Importación de
CreateThread
:Usamos P/Invoke para importar la función
CreateThread
desde la bibliotecakernel32.dll
. Esto nos permite llamar a esta función nativa de Windows directamente desde C#.
Creación del Hilo:
Llamamos a
CreateThread
pasando los parámetros adecuados:IntPtr.Zero
se pasa para usar los valores predeterminados en los atributos del hilo y la pila.El delegado
MiMetodo
es el que se ejecutará en el hilo.IntPtr.Zero
se pasa porque no necesitamos parámetros adicionales para el hilo.0
para losdwCreationFlags
, lo que significa que el hilo se ejecutará inmediatamente.
Ejecución Concurrente:
El método
MiMetodo
se ejecuta en el hilo creado porCreateThread
. Este método imprime los números del 0 al 4 con un retardo de un segundo entre cada impresión gracias aThread.Sleep(1000)
.
Esperar la Entrada del Usuario:
Dado que
CreateThread
crea el hilo en segundo plano, la ejecución del hilo no detiene el flujo principal del programa. Por lo tanto, utilizamosConsole.ReadKey()
para hacer una pausa y permitir que el usuario vea la salida del hilo antes de que la aplicación termine.
Last updated