Cerramos del 11/08 al 15/08. Los pedidos cursados a partir del 08/08 a las 12.00 hora de España peninsular se tramitarán el 18/08/2025.
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí

Conceptos avanzados

Asincronismo

1. Funcionamiento básico

Antes de abordar el asincronismo de manera detallada, es necesario introducir algunos conceptos, especialmente para comprender correctamente dos ideas que son distintas, pero a menudo se confunden: el paralelismo y el asincronismo.

En esta sección vamos a tratar el concepto de asincronismo, que consiste en relegar una operación a un segundo plano y seguir ejecutando el código restante cuando se ha terminado la operación. Para comprender correctamente la lógica detrás del asincronismo, podemos intentar hacer una comparación con un ejemplo de la vida diaria.

Cuando ponemos en marcha una lavadora, esta realiza su trabajo de manera asíncrona respecto a nosotros, lo que permite, durante este tiempo, que podamos ocuparnos de otra cosa. Cuando ha terminado el ciclo, emite un sonido para avisar, y se puede recoger la ropa para tenderla. Considerando que somos el programa principal, y que la ropa es el código que se debe ejecutar de manera asíncrona, podemos observar el concepto de asincronismo.

Tan pronto como metamos la ropa dentro de la máquina y la pongamos en marcha, delegamos el trabajo aplicado a esta ropa a otra entidad que no somos nosotros. Durante ese trabajo, podemos retomar nuestro propio trabajo. Aquí tenemos el concepto de asincronismo. Cuando el lavado haya terminado, la máquina emitirá una señal sonora a fin de que saquemos la ropa y la tendamos. Este es el concepto de asincronismo: la máquina ha trabajado de manera asíncrona con relación a nosotros.

En cuanto al paralelismo, se trata de hacer varias cosas al mismo tiempo. Por ejemplo, si elegimos poner en marcha una lavadora y, en el mismo intervalo, también ponemos en marcha el lavavajillas, las dos máquinas funcionarán en paralelo consumiendo recursos compartidos (agua y electricidad). Esto permite optimizar el tiempo de ejecución compartiendo los mismos recursos.

No se deben confundir los dos conceptos, aunque sean complementarios. Especialmente porque el uso de uno u otro depende en gran medida del uso buscado:

  • El asincronismo se usa cuando queremos acceder a un recurso sobre el que no tenemos control respecto al tiempo de acceso (lectura de archivo, recurso de red, base de datos, consulta web, etc.). También podemos usar el asincronismo cuando queremos ejecutar una parte de código...

Algoritmia avanzada

Durante todo el libro, hemos estudiado la algoritmia básica, que permite abarcar un amplio perímetro funcional. Sin embargo, C# y el framework .NET tienen una cantidad enorme de funcionalidades más avanzadas. En este capítulo vamos a estudiar algunas.

1. Programación dirigida por eventos

La programación dirigida por eventos permite reaccionar a eventos que se producen durante la ejecución de una aplicación. Hasta ahora, hemos reaccionado de manera síncrona a un evento particular (como, por ejemplo, esperar a que el usuario introduzca un valor en la consola). Sin embargo, C# proporciona un mecanismo potente que permite hacer programación reactiva, es decir, no esperar a un evento cualquiera, sino reaccionar solo cuando se produzca un evento particular.

a. Los delegate

Para entender bien el tema, es necesario comprender un principio que se remonta a C# 2: los delegate. Un delegate es el equivalente de un descriptor de un método, y una variable de tipo delegate corresponde a un puntero efectivo hacia un método.

Para declarar un delegate, hay que usar la palabra clave dedicada, delegate; luego declarar la firma de método a la que queremos representar, con su tipo de retorno y sus posibles parámetros (o paréntesis vacíos si no hay ningún parámetro):

public delegate void MiDelegadoVoidSinParametros(); 
public delegate string MiDelegadoDevuelveString(); 
public delegate void MiDelegadoVoidConParametros(string data); 

En el bloque de código anterior, hemos declarado tres delegate:

  • El primero permite representar a un método que devuelve void y no toma parámetros.

  • El segundo permite representar a un método que devuelve un string y no toma parámetros.

  • El tercero permite representar a un método que devuelve void y toma un parámetro de tipo string.

Los delegate se pueden declarar en una clase y solo se podrán usar dentro de esta última. Si no, también se pueden declarar directamente en un espacio de nombres (al mismo nivel que una clase) para usarlos en varias clases.

Una vez definido un delegate, podemos declarar una variable del tipo del delegate y hacerlo apuntar hacia cualquier método que tenga la firma requerida: 

public delegate void MiDelegadoVoidSinParametros(); 
public class Cap7Delegates 
{ 
    public...