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