Wie benachrichtige ich mehrere Clients möglichst ohne Zeitverlust und ohne das Rad neu zu erfinden?
Eine weitverbreitete Möglichkeit ist das Observer Pattern (und erweitert, das Subscriber Pattern).
Es ist push-basiert, der Beobachtete gibt also allen Beobachtern Bescheid, was eine Benachrichtigung an die Beobachter in kürzester Zeit ermöglicht.

ObserverPattern

Was wir in Java dafür brauchen sind folgende Klassen und Interfaces, welche wir im Code referenzieren. In C# gibt es keine äquivalenten Klassen, wir müssen etwas selber schreiben.

Java
import java.util.Observable;
import java.util.Observer;

Erstellen wir nun die Klasse, welche später beobachtet werden soll.
In C# nutzen wir EventHandler für eine asynchrone Benachrichtigung:

JavaC#
public class Beobachteter extends Observable
public class Observable
	{
		private bool changed;
		event EventHandler notifier;
		
		public void addObserver(Observer obs)
		{
			notifier += obs.update;
		}
	
		private void notifyObservers(dynamic obj)
		{
			if (this.changed) {
				if(notifier != null)
					 notifier(obj, EventArgs.Empty);
			}
			this.changed = false;
		}
		
		public void setChanged()
		{
			this.changed = true;
		}
		
		public void doIt(){
			setChanged();
			notifyObservers(32123);
		}
		
	}

Wir lassen unseren Beobachteten die Klasse Observable im Namespace java.util.* erben. (Siehe oben)
Dadurch bekommt die Klasse u.A. folgende Methode vererbt, welche wir im Folgenden nutzen:

JavaC#
public void AddObserver(){
       Beobachteter.addObserver(Observer o);
}
 Durch die eigene Implementierung, stehen uns die identischen Methoden zur Verfügung. 

Wie man auf dem Bild sieht, muss man nun die Beobachter (Observer) einem Beobachtbaren (Observable) hinzufügen, im Folgenden nenne ich diesen dann Beobachteten.
Wir erstellen verschiedene Beobachter und fügen diese nun einem Objekt der Klasse Beobachteter zu, welche – der Einfachheit halber – direkt in den Beobachtern erstellt wird.
Die Beobachter implementieren das Interface von java.util.Observer.

JavaC#
public class Beobachter implements Observer{
    public Beobachter(){
         Beobachteter observable = new Beobachteter();
         observable.addObserver(this); //fügt dem Beobachteten mich als Beobachter hinzu.
    }
}
 	public class Observer
	{
		string name;
		
		public Observer()
		{
		}
		
		public Observer(string name){
			this.name = name;
		}
	
		public void update(object message, EventArgs args){
			//Console.WriteLine(this + "received: "+message+obs);
		}
		
		public override string ToString()
		{
			return "{Observer,"+this.name+"}";
		} 
	}

Nun haben wir einen oder mehrere Beobachter und einen Beobachteten.
Wie lassen wir die Beobachter nun wissen, wenn sich etwas ändert?
Die Klasse Observable bietet hier einige passende Methoden. Ich fokussiere mich hier allerdings auf folgende zwei:

JavaC#
 setChanged(); 
 notifyObservers(message);
setChanged();  
notifyObservers(message);

Durch das dynamic keyword können wir dem EventHandler „notifier“ jegliche Daten als Parameter durchreichen, diese Implementierung vereinfacht das Handling der Daten extrem.

setChanged() ist von Nöten, da ein Beobachter auch nur benachrichtigt wird, wenn sich auch etwas geändert hat.
In Java ist es zudem sehr praktisch, dass man jede Art von Daten in der Methode

notifyObservers();

versenden kann. Mit dieser werden die Beobachter auch benachrichtigt.

Im Java Observer wird nun die Methode

update(Observable _ob, Object message)

, welche wir durch das Interface implementierten, ausgeführt.
In C# rufen der EventHandler die Observer-Methode

 update(dynamic message, EventArgs empty) 

aus.

Im Anhang befindet sich das C# Test Projekt, als .sln Solution:
ObserverPattern