Introduction
This article demonstrates how to implement an event which supports only a single listener, i.e., at a given point of time only one client can subscribe to that event. By default, for events, all the clients subscribing will get notified in a sequential order, but in this case, only the client subscribing last will get notified.
This type of an event is useful when we have multiple threads running which subscribe for a particular event notification, but it is enough that this notification is processed by only one thread. In the case of normal events, all the threads will get the notification and all threads will start processing the notification. In this case, the event will not be sent to all the threads, only the last subscribing thread will receive the notification. Hence, the notification processing method may not be thread safe (can avoid kernel objects for synchronization).
Background
In .NET, by default, events exhibit multicast behavior, i.e., an event notification is sent to all the clients who are subscribed to the event in the order in which they have subscribed. There will be a list of delegates subscribing to the event and notification is sent to all of them in an order. The problem here is if any one of the handlers throw an exception then the rest of the handlers will not get the notification, even if this exception is handled by the event raiser. Some times (as in the above case), we require an event which holds only one event handler, i.e., it won't pile up a list of handlers and exhibit a single-cast behavior.
Using the code
Run the SinglecastEvent.exe, and a form will be displayed which contains three buttons and a text box to display messages. Click on the "Client 1" button. Now, Client 1 is registered to an event which will be raised on clicking the "Raise event" button. The Client 1 message handler will display the message in the messages text box. Now, click on the "Client 2" button. On clicking the "Raise event" button again, the event will be handled only by the Client 2 message handler and Client 1 will not receive the notification.
The code contains a class EventRaiser
which raises an event when the "Raise event" button is clicked. This class raises the "OnRaiseEvent
" event and clients (forms) handle this event. The OnRaiseEvent
is implemented as below:
private EventHandler OnRaiseEventHandler;
public event EventHandler OnRaiseEvent
{
add
{
OnRaiseEventHandler = value;
}
remove
{
OnRaiseEventHandler -= value;
}
}
private void btnClient1_Click(object sender, System.EventArgs e) {
txtMessages.Text += "Client 1 subscribed to event," +
" other clients will stop listening to event. " +
Environment.NewLine;
eventRaiser.OnRaiseEvent +=
new EventHandler(Client1_OnRaiseEventHandler);
}
private void btnClient2_Click(object sender, System.EventArgs e) {
txtMessages.Text += "Client 2 subscribed to event, " +
"other clients will stop listening to event." +
Environment.NewLine;
eventRaiser.OnRaiseEvent +=
new EventHandler(Client2_OnRaiseEventHandler);
}
private void Client1_OnRaiseEventHandler(object sender, EventArgs e)
{
txtMessages.Text += "Client 1 : event received." +
Environment.NewLine;
}
private void Client2_OnRaiseEventHandler(object sender, EventArgs e)
{
txtMessages.Text += "Client 2 : event received." +
Environment.NewLine;
}
private void btnRaiseEvent_Click(object sender, System.EventArgs e) {
eventRaiser.RaiseEvent();
}