Il stocke le fournisseur de synchronisation, une classe dérivée de SynchronizationContext. Dans ce cas, ce sera probablement une instance de WindowsFormsSynchronizationContext. Cette classe utilise les méthodes Control.Invoke() et Control.BeginInvoke() pour implémenter les méthodes Send() et Post(). Ou bien il peut s'agir de DispatcherSynchronizationContext, elle utilise alors Dispatcher.Invoke() et BeginInvoke(). Dans une application Winforms ou WPF, ce fournisseur est automatiquement installé dès que vous créez une fenêtre.
Lorsque vous exécutez du code sur un autre thread, comme le thread-pool utilisé dans le snippet, vous devez faire attention à ne pas utiliser directement des objets qui ne sont pas sûrs pour les threads. Comme tout objet d'interface utilisateur, vous devez mettre à jour la propriété TextBox.Text à partir du thread qui a créé le TextBox. La méthode Post() garantit que la cible du délégué s'exécute sur ce thread.
Attention, ce snippet est un peu dangereux, il ne fonctionnera correctement que si vous l'appelez depuis le thread UI. SynchronizationContext.Current a des valeurs différentes dans les différents threads. Seul le thread UI a une valeur utilisable. C'est la raison pour laquelle le code a dû la copier. Une façon plus lisible et plus sûre de le faire, dans une application Winforms :
ThreadPool.QueueUserWorkItem(delegate {
string text = File.ReadAllText(@"c:\temp\log.txt");
myTextBox.BeginInvoke(new Action(() => {
myTextBox.Text = text;
}));
});
Ce qui a l'avantage de fonctionner lorsqu'il est appelé à partir de tout fil. L'avantage d'utiliser SynchronizationContext.Current est que cela fonctionne toujours, que le code soit utilisé dans Winforms ou WPF, peu importe dans une bibliothèque. C'est certainement no un bon exemple d'un tel code, vous savez toujours quel type de TextBox vous avez ici, donc vous savez toujours s'il faut utiliser Control.BeginInvoke ou Dispatcher.BeginInvoke. En fait, l'utilisation de SynchronizationContext.Current n'est pas si courante.
Le livre essaie de vous enseigner l'enfilage, donc l'utilisation de cet exemple imparfait est acceptable. Dans la vie réelle, dans les quelques cas où vous puede Si vous envisagez d'utiliser SynchronizationContext.Current, vous laisserez toujours aux mots-clés async/await de C# ou à TaskScheduler.FromCurrentSynchronizationContext() le soin de le faire pour vous. Mais notez qu'ils se comportent toujours mal, comme le fait le snippet, lorsque vous les utilisez sur le mauvais thread, pour la même raison. Une question très fréquente par ici, le niveau d'abstraction supplémentaire est utile mais rend plus difficile de comprendre pourquoi ils ne fonctionnent pas correctement. Espérons que le livre vous indique également quand ne pas l'utiliser :)