Invocación de delegados multidifusión.

En .NET, cuando queremos invocar un delegado multidifusión, aquel que puede tener más de un elemento en su lista de invocación, debemos tener en cuenta que si lanzamos estás invocaciones de forma síncrona, en caso de que una de ellas lance una excepción el resto no se invocarán, quizás este sea el comportamiento que buscamos o quizás queramos lanzar el resto de invocaciones, aunque una hubiera producido una excepción.

Veámoslo con un ejemplo

Creamos un programa de consola al que le agregamos una clase estática Listener con tres métodos que serán los subscriptores que queremos invocar, hemos forzado el lanzamiento de una excepción por parte del segundo método para ver cómo se comportan las distintas invocaciones que realizaremos.

 

using System;

namespace MultiDelegates
{
public static class Listener
{
public static void FirstListener(object obj, EventArgs e)
{
Console.WriteLine("FirstListener Received Event");
}
public static void SecondListener(object obj, EventArgs e)
{
Console.WriteLine("SecondListener Received Event");
throw new Exception("Exception on listener");
}
public static void ThirdListener(object obj, EventArgs e)
{
Console.WriteLine("Third Received Event");
}
}
}

Por otro lado crearemos una clase MultiDelegateEventHandler que contendrá un eventhandler al que le podremos agregar las invocaciones

 

EventHandler somethingHappened;

public void AttachListener(EventHandler handler)

{

Console.WriteLine("Registering event:{0} ", handler.Method.Name);

somethingHappened += handler;

}

Inicializamos la lista de invocación agregándoles los tres métodos del listener, el segundo lanzará una excepción.

 

MultiDelegateEventHandler evh = new MultiDelegateEventHandler();

evh.AttachListener(Listener.FirstListener);

evh.AttachListener(Listener.SecondListener);

evh.AttachListener(Listener.ThirdListener);

Invocación síncrona

En primer lugar llamaremos a la invocación síncrona

public void InvokeFirstWay()

{ 
 this.somethingHappened.Invoke(this, null);
 }

Vemos que ejecuta el primer método y el segundo, pero al lanzar este una excepción no continua con el tercero.

Invocación síncrona controlada

Accederemos a la lista de invocación de este delegado, lanzaremos una a una sus subscripciones y capturaremos posbles excepciones

 

foreach (EventHandler h in somethingHappened.GetInvocationList())

{

try

{

h(this, null);

}

catch (Exception ex)

{

var color = Console.ForegroundColor;

Console.ForegroundColor = ConsoleColor.Red;

Console.WriteLine(ex.Message);

Console.ForegroundColor = color;

}

}

Vemos que ejecuta el primer método, el segundo y la excepción es capturada para poder continuar con el tercero.

Invocación asíncrona

Otra forma es dejar a los subscriptores que gestionen la invocación en otro hilo, el proceso lanzará un “Fire and forget”, de forma que no recibirá la excepción del segundo método.

 

public void InvokeThirdWay()

{

foreach (EventHandler h in somethingHappened.GetInvocationList())

{

 

h.BeginInvoke(somethingHappened, null, null, null);

}

}.

Vemos que ejecuta el primer método, el segundo y el tercero de forma asíncrona.

Etiquetas:, ,

Deja un comentario

Si continuas utilizando este sitio aceptas el uso de cookies. más información

Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

Cerrar