Los delegados son ejecutados en un orden secuencial. Generalmente, los delegados son ejecutados en el orden en que fueron agregados, aunque esto no es algo que es especifico dentro del Common Language Infraestructure (CLI), no debería depender de esto.
Una cosa que es un resultado directo del orden secuencial de ejecución es el manejo de las excepciones. Como en el siguiente ejemplo tenemos un suscriptor del event lanza un error.
using System;
namespace ExceptionWhenRaisingEvent
{
public class Pub
{
public event EventHandler OnChange = delegate { };
public void Raise()
{
OnChange(this, EventArgs.Empty);
}
}
class Program
{
static void Main(string[] args)
{
CreateAndRaise();
}
public static void CreateAndRaise()
{
Pub p = new Pub();
p.OnChange += (sender, e)
=> Console.WriteLine("Suscriptor 1 llamado");
p.OnChange += (sender, e)
=> { throw new Exception(); };
p.OnChange += (sender, e)
=> Console.WriteLine("Suscriptor 1 llamado");
p.Raise();
}
}
}
Como puede ver, el primer subscriptor es ejecutado con éxito. el segundo lanza una excepción, y el tercero nunca es llamado.
Si este no es el comportamiento que usted quiere, necesita manualmente lanzar los eventos y manejar cualquier excepción que ocurra. Puede hacer esto usando el método GetInvocationList que es declarado en la clase base System.Delegate.
using System;
using System.Collections.Generic;
using System.Linq;
namespace RaiseEventWhitExceptionManual
{
public class Pub
{
public event EventHandler OnChange = delegate { };
public void Raise()
{
var exceptions = new List<Exception>();
foreach (Delegate handler in OnChange.GetInvocationList())
{
try
{
handler.DynamicInvoke(this, EventArgs.Empty);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
if (exceptions.Any())
{
throw new AggregateException(exceptions);
}
}
}
class Program
{
static void Main(string[] args)
{
CreateAndRaise();
}
public static void CreateAndRaise()
{
Pub p = new Pub();
p.OnChange += (sender, e)
=> Console.WriteLine("Llamando al Subscriptor 1");
p.OnChange += (sender, e)
=> { throw new Exception(); };
p.OnChange += (sender, e)
=> Console.WriteLine("Llamando al Subscriptor 3");
try
{
p.Raise();
}
catch (AggregateException ex)
{
Console.WriteLine(ex.InnerExceptions.Count);
}
}
}
}
Resultado
Exam Ref 70-483 Programming in C#




