Es speichert den Synchronisationsanbieter, eine von SynchronizationContext abgeleitete Klasse. In diesem Fall handelt es sich wahrscheinlich um eine Instanz von WindowsFormsSynchronizationContext. Diese Klasse verwendet die Methoden Control.Invoke () und Control.BeginInvoke (), um die Methoden Send () und Post () zu implementieren. Oder es kann DispatcherSynchronizationContext sein, es verwendet Dispatcher.Invoke () und BeginInvoke (). In einer Winforms- oder WPF-App wird dieser Anbieter automatisch installiert, sobald Sie ein Fenster erstellen.
Wenn Sie Code in einem anderen Thread ausführen, wie z. B. dem im Snippet verwendeten Thread-Pool-Thread, müssen Sie darauf achten, dass Sie keine direkt threadsicheren Objekte verwenden. Wie bei jedem Benutzeroberflächenobjekt müssen Sie die Eigenschaft TextBox.Text aus dem Thread aktualisieren, der die TextBox erstellt hat. Die Post () -Methode stellt sicher, dass das Delegatenziel auf diesem Thread ausgeführt wird.
Beachten Sie, dass dieses Snippet etwas gefährlich ist. Es funktioniert nur dann ordnungsgemäß, wenn Sie es über den UI-Thread aufrufen. SynchronizationContext.Current hat unterschiedliche Werte in unterschiedlichen Threads. Nur der UI-Thread hat einen verwendbaren Wert. Und ist der Grund, warum der Code es kopieren musste. Eine besser lesbare und sicherere Möglichkeit, dies in einer Winforms-App zu tun:
ThreadPool.QueueUserWorkItem(delegate {
string text = File.ReadAllText(@"c:\temp\log.txt");
myTextBox.BeginInvoke(new Action(() => {
myTextBox.Text = text;
}));
});
Was den Vorteil hat, dass es funktioniert, wenn es von einem beliebigen Thread aufgerufen wird. Der Vorteil der Verwendung von SynchronizationContext.Current besteht darin, dass es weiterhin funktioniert, unabhängig davon, ob der Code in Winforms oder WPF verwendet wird. Dies ist in einer Bibliothek von Bedeutung. Dies ist sicherlich kein gutes Beispiel für einen solchen Code. Sie wissen immer, welche Art von TextBox Sie hier haben, sodass Sie immer wissen, ob Sie Control.BeginInvoke oder Dispatcher.BeginInvoke verwenden sollen. Tatsächlich ist die Verwendung von SynchronizationContext.Current nicht so häufig.
Das Buch versucht, Ihnen das Einfädeln beizubringen, daher ist es in Ordnung, dieses fehlerhafte Beispiel zu verwenden. In der Praxis können Sie in den wenigen Fällen, in denen Sie die Verwendung von SynchronizationContext.Current in Betracht ziehen, die Schlüsselwörter async / await von C # oder TaskScheduler.FromCurrentSynchronizationContext () für Sie verwenden. Beachten Sie jedoch, dass sie sich aus genau demselben Grund immer noch schlecht verhalten wie das Snippet, wenn Sie sie im falschen Thread verwenden. Eine sehr häufige Frage ist, dass die zusätzliche Abstraktionsebene nützlich ist, es jedoch schwieriger macht, herauszufinden, warum sie nicht richtig funktionieren. Hoffentlich sagt dir das Buch auch, wann du es nicht benutzen sollst :)