Читать книгу Dojos für Entwickler 2 - Stefan Lieser - Страница 54
Listing 6 Synchronizer für Windows Forms.
Оглавлениеpublic class Synchronizer<T> { private readonly SynchronizationContext synchronizationContext; public Synchronizer() { synchronizationContext = SynchronizationContext.Current ?? new SynchronizationContext(); } public void Process(T input) { synchronizationContext.Send(_ => Result(input), null); } public event Action<T>Result; }
Der SynchronizationContext wird im Konstruktor des Bausteins ermittelt und in einem Feld des Synchronizers abgelegt. Auf diese Weise steht er in der Process-Methode zur Verfügung, um mittels Send eine Lambda-Expression an den Zielthread zu übergeben. Die Lambda-Expression ruft wieder den Result-Event auf, wie das beim Asynchronizer schon der Fall war. Damit der Synchronizer funktioniert, muss sein Konstruktor auf dem Thread aufgerufen werden, auf den später synchronisiert werden soll. Normalerweise ist das der Hauptthread, auf dem das Programm initialisiert wird. Aber Obacht!
Der SynchronizationContext funktioniert nicht mit beliebigen Threads. Windows Forms treibt hinter den Kulissen etwas Magie. Es realisiert nämlich eine Message-Loop, die dafür sorgt, dass Aufrufe an den UI-Thread übergeben werden können. Zwischen beliebigen Threads zu synchronisieren ist auf diese Weise nicht möglich. Eine allgemeine Lösung dieses Problems würde allerdings den Rahmen der übung sprengen. Für die Praxis ist das kein Beinbruch, da die Synchronisierung in aller Regel im Zusammenhang mit dem UI auftritt. Genau in diesem Szenario funktionieren SynchronizationContext bzw. Dispatcher bei WPF und Silverlight wunderbar.
Doch wie testet man nun den Synchronizer? Ich sehe hier im Wesentlichen zwei Aspekte, die durch automatisierte Tests sichergestellt werden sollten :
Zum einen muss sichergestellt sein, dass der Eingangsparameter der Process-Methode an den Result-Event übergeben wird. Der Flow darf schließlich nicht unterbrochen werden.
Zum anderen sollte ein Test sicherstellen, dass der Eventhandler, der durch den Result-Event ausgelöst wird, auf dem korrekten Thread abläuft.
Für den zweiten Test ist zu berücksichtigen, dass dies nur im Rahmen einer Windows-Forms-Anwendung funktioniert. Der erste Test für den Synchronizer erfolgt analog zum Test des Asynchronizers: Die Process-Methode wird mit einem Parameter aufgerufen, um anschließend zu überprüfen, ob der Result-Event den Parameter wieder mitführt, siehe Listing 7.