Przechowuje dostawcę synchronizacji, klasę pochodzącą z SynchronizationContext. W tym przypadku prawdopodobnie będzie to wystąpienie WindowsFormsSynchronizationContext. Ta klasa używa metod Control.Invoke () i Control.BeginInvoke () do implementacji metod Send () i Post (). Lub może to być DispatcherSynchronizationContext, używa Dispatcher.Invoke () i BeginInvoke (). W aplikacji Winforms lub WPF ten dostawca jest automatycznie instalowany zaraz po utworzeniu okna.
Kiedy uruchamiasz kod w innym wątku, takim jak wątek puli wątków używany we fragmencie, musisz uważać, aby nie używać bezpośrednio obiektów, które nie są bezpieczne dla wątków. Podobnie jak w przypadku każdego obiektu interfejsu użytkownika, należy zaktualizować właściwość TextBox.Text z wątku, który utworzył TextBox. Metoda Post () zapewnia, że docelowy delegat działa w tym wątku.
Uważaj, ten fragment kodu jest nieco niebezpieczny, będzie działał poprawnie tylko wtedy, gdy wywołasz go z wątku interfejsu użytkownika. SynchronizationContext.Current ma różne wartości w różnych wątkach. Tylko wątek interfejsu użytkownika ma użyteczną wartość. I to jest powód, dla którego kod musiał go skopiować. Czytelniejszy i bezpieczniejszy sposób na zrobienie tego w aplikacji Winforms:
ThreadPool.QueueUserWorkItem(delegate {
string text = File.ReadAllText(@"c:\temp\log.txt");
myTextBox.BeginInvoke(new Action(() => {
myTextBox.Text = text;
}));
});
Co ma tę zaletę, że działa przy wywołaniu z dowolnego wątku. Zaletą korzystania z SynchronizationContext.Current jest to, że nadal działa niezależnie od tego, czy kod jest używany w Winforms czy WPF, ma to znaczenie w bibliotece. Z pewnością nie jest to dobry przykład takiego kodu, zawsze wiesz, jaki masz tutaj TextBox, więc zawsze wiesz, czy użyć Control.BeginInvoke czy Dispatcher.BeginInvoke. W rzeczywistości używanie SynchronizationContext.Current nie jest tak powszechne.
Książka próbuje cię nauczyć o gwintowaniu, więc użycie tego błędnego przykładu jest w porządku. W prawdziwym życiu, w nielicznych przypadkach, gdy może rozważyć użycie SynchronizationContext.Current, że ty nadal pozostawić go do C # 's async / Oczekujcie słowa kluczowe lub TaskScheduler.FromCurrentSynchronizationContext (), aby zrobić to za Ciebie. Ale pamiętaj, że nadal źle zachowują się tak, jak fragment kodu, gdy używasz ich w niewłaściwym wątku, z dokładnie tego samego powodu. Bardzo częste tutaj pytanie, dodatkowy poziom abstrakcji jest przydatny, ale utrudnia ustalenie, dlaczego nie działają poprawnie. Mam nadzieję, że książka podpowie Ci, kiedy jej nie używać :)