Iniciar hilos en C# mediante delegados

A continuación se presentna ejempols prácticos de cómo iniciar un hilo secundario usendo delegados en C#. Se muestra la ejecución asíncrona de un método con parámetros y valor de retorno, y tres formas de detectar su finalización.

Método de prueba

static int Sumar(int a, string texto)
{
    Console.WriteLine($"Sumar-{a}-{texto}-Hilo ID: {Thread.CurrentThread.ManagedThreadId}");
    Thread.Sleep(100);
    return a * 2;
}

1. Espera activa (polling) con IsCompleted

static void EjemploEsperaActiva()
{
    Func<int, string, int> del = Sumar;
    IAsyncResult asyncResult = del.BeginInvoke(5, "demo", null, null);

    while (!asyncResult.IsCompleted)
    {
        Console.WriteLine($"Esperando que el hilo termine. Hilo principal ID: {Thread.CurrentThread.ManagedThreadId}");
        Thread.Sleep(10);
    }

    int resultado = del.EndInvoke(asyncResult);
    Console.WriteLine($"Hilo finalizado. Resultado: {resultado}. Hilo principal ID: {Thread.CurrentThread.ManagedThreadId}");
}

Ejecución desde Main:

Console.WriteLine($"Hilo principal iniciado. ID: {Thread.CurrentThread.ManagedThreadId}");
EjemploEsperaActiva();

Salida típica:

Hilo principal iniciado. ID: 1
Esperando que el hilo termine. Hilo principal ID: 1
Sumar-5-demo-Hilo ID: 3
Esperando que el hilo termine. Hilo principal ID: 1
...
Hilo finalizado. Resultado: 10. Hilo principal ID: 1

2. Uso de AsyncWaitHandle con tiempo de espera

static void EjemploWaitHandle()
{
    Func<int, string, int> del = Sumar;
    IAsyncResult asyncResult = del.BeginInvoke(3, "prueba", null, null);

    bool finalizado = asyncResult.AsyncWaitHandle.WaitOne(80); // 80 ms de espera
    if (finalizado)
    {
        int resultado = del.EndInvoke(asyncResult);
        Console.WriteLine($"Finalizó dentro del tiempo. Resultado: {resultado}. Hilo principal ID: {Thread.CurrentThread.ManagedThreadId}");
    }
    else
    {
        Console.WriteLine($"No finalizó en 80 ms. Continuando. Hilo principal ID: {Thread.CurrentThread.ManagedThreadId}");
        int resultado = del.EndInvoke(asyncResult);
        Console.WriteLine($"Finalizó después. Resultado: {resultado}. Hilo principal ID: {Thread.CurrentThread.ManagedThreadId}");
    }
}

Ejecución:

Console.WriteLine($"Hilo principal iniciado. ID: {Thread.CurrentThread.ManagedThreadId}");
EjemploWaitHandle();

Salida típica:

Hilo principal iniciado. ID: 1
Sumar-3-prueba-Hilo ID: 3
No finalizó en 80 ms. Continuando. Hilo principal ID: 1
Finalizó después. Resultado: 6. Hilo principal ID: 1

3. Callback al finalizar el hilo

static void EjemploCallback()
{
    Func<int, string, int> del = Sumar;
    del.BeginInvoke(7, "callback", CallbackTermino, del);

    // También se puede usar una expresión lambda:
    // del.BeginInvoke(7, "callback", ar =>
    // {
    //     int res = del.EndInvoke(ar);
    //     Console.WriteLine($"En lambda, resultado: {res}");
    // }, null);
}

static void CallbackTermino(IAsyncResult ar)
{
    Func<int, string, int> del = ar.AsyncState as Func<int, string, int>;
    int resultado = del.EndInvoke(ar);
    Console.WriteLine($"En el callback, resultado obtenido: {resultado}. Hilo ID: {Thread.CurrentThread.ManagedThreadId}");
}

Ejecución:

static void Main(string[] args)
{
    Console.WriteLine($"Hilo principal iniciado. ID: {Thread.CurrentThread.ManagedThreadId}");
    EjemploCallback();
    Console.ReadKey();
}

Salida típica:

Hilo principal iniciado. ID: 1
Sumar-7-callback-Hilo ID: 3
En el callback, resultado obtenido: 14. Hilo ID: 3

Etiquetas: C# delegates threading asynchronous AsyncCallback

Publicado el 7-16 16:07