2009-06-01 7 views
7

Mi clase tiene un evento que los objetos externos se suscriben a:Forwarding/retransmisión de eventos .NET

public event EventHandler<MessageReceivedEventArgs> MessageReceived; 

Sin embargo, un objeto de detector interno, que se ejecuta en su propio hilo, será en realidad se origina el evento.

private class Listener 
{ 
    public void Run() 
    { 
     // events raised here which should be forwarded 
     // to parent's MessageReceived 
    } 
}; 

Mi inclinación es crear un evento con la misma firma en el oyente, y suscribirse a él en la clase principal con el fin de elevarlo en MessageReceived. Esto parece un poco engorroso, así que me preguntaba si existe una forma ordenada/idiomática de enviar eventos como este.

Respuesta

22

Usted puede utilizar el evento add/remove accessors para que los eventos cableadas al evento de cara al exterior están "enviados" a la escucha interna

public event EventHandler<MessageReceivedEventArgs> MessageReceived { 
    add { this.listener.MessageRecieved += value; } 
    remove { this.listener.MessageRecieved -= value; } 
} 

Esto significa que necesita para crear un evento en el oyente, pero el beneficio es que no hay otra fontanería para conectar el evento.

+8

Esta es una buena solución, pero tenga en cuenta que el controlador de eventos recibirá la instancia de escucha como el argumento emisor, que puede ser un problema ... –

+0

Niza, me gusta! – marijne

+1

también un buen punto sobre el remitente ... – marijne

1

Podría hacer eso con un evento, o podría crear un método en su clase principal llamado ReceiveMessage() y llamarlo desde el oyente (y luego plantear el evento desde allí).

1

Como se ha respondido, puede tener una lógica de suscripción personalizada mediante la adición y eliminación de controladores en su evento.

Tenga en cuenta que este diseño tiene un problema como está. Usted especifica que su oyente está planteando el evento en su propio hilo. De forma predeterminada, los manejadores se invocarán en la secuencia que generó el evento (en su caso, el hilo del Oyente). Tienes varias opciones.

  • Si no le importa que el hilo del oyente ejecute las devoluciones de llamada. Sólo tiene que llamar al evento como es (pero su hebra de escucha puede ser bloqueada si un manejador de sucesos toma un tiempo para ejecutar, o simplemente morir si un controlador de eventos se produce una excepción no controlada)
  • Si desea que los controladores se ejecutan en hilos diferentes que el oyente hilo, pero no me importa que se enrosca en la medida en que no está en el oyente: en el método OnXxx que realmente llama a los controladores, obtener la lista de invocación del evento y la cola de cada controlador en el conjunto de subprocesos.
  • si desea que los manipuladores a ser llamados en las discusiones específicas: un poco complicado, hay que utilizar un poco de SynchronizationContext (WindowsSynchronizationContext en Winforms, uno personalizado en otros casos, etc.)

Hay una entrada en el blog por Roy Osherove mostrando varias maneras de hacer las llamadas asíncronas: http://weblogs.asp.net/rosherove/pages/DefensiveEventPublishing.aspx (pero yo no usaría las llamadas asíncronas de delegados y en lugar de invocar directamente la ThreadPool para llamar a los delegados).

Cuestiones relacionadas