Читать книгу Dojos für Entwickler 2 - Stefan Lieser - Страница 64
Gather
ОглавлениеAufgabe des Gather-Bausteins ist es, die Aufzählungen, die an den beiden Eingängen anstehen, zu einer Aufzählung für den Ausgang zusammenzufassen. Dabei wird der Ausgang auf einem eigenen Thread ausgeführt, damit der Baustein nicht blockiert. Bei der Implementation habe ich zunächst auf eine ConcurrentQueue und einen AutoResetEvent gesetzt. Doch dabei kam es sporadisch dazu, dass der Baustein blockierte. Die Synchronisierung der beiden Eingänge ist nicht so trivial, wie es zunächst den Anschein haben mag. Doch das .NET Framework hält eine weitere Datenstruktur bereit, die in diesem Fall die Lösung bedeutete: eine BlockingCollection. Die bewerkstelligt genau, was ich gebraucht habe: Auf der Eingangsseite sollen Daten in die BlockingCollection ergänzt werden können. Mit der Add-Methode ist das kein Problem. Und da diese Datenstruktur threadsicher ist, können auch beide Eingänge asynchron Einträge ergänzen, ohne dass es zu Problemen kommt.
Auf der Ausgangsseite liegt die Herausforderung. Hier können natürlich nur Elemente entnommen werden, wenn welche vorhanden sind. Wenn kein Eintrag vorhanden ist, muss der Thread, auf dem der Ausgangsevent des Gather-Bausteins läuft, angehalten werden. Erst wenn auf der Eingangsseite wieder ein Element ergänzt wird, soll der Thread weiterlaufen. Thread.Sleep kommt nicht infrage, so viel dürfte inzwischen klar sein. Ursprünglich hatte ich hier den AutoResetEvent verwendet, um auf neue Daten zu warten. Doch die BlockingCollection macht genau, was ich brauche: Sie blockiert, wenn keine Daten anliegen. Man kann sie daher gefahrlos iterieren. Im MoveNext des zugrunde liegenden Enumerators wird der Thread so lange angehalten, bis Daten anliegen. Damit sieht meine Implementation des Gather-Bausteins so wie in Listing 13 aus.