811
Потоковые.модели.приложений
приложениями, просто вы не видите консоль) не навязывают
никакой потоковой
модели; то есть поток может делать все, что он хочет и когда хочет.
Однако приложения с графическим пользовательским интерфейсом (GUI),
в том числе приложения Windows Forms, Windows Presentation Foundation (WPF),
Silverlight и Windows Store, предлагают такую модель, в которой обновлять окно
можно только создавшему его потоку. GUI-потоки обычно порождают асинхронные
операции, чтобы предотвратить блокировку и не допустить отсутствия реакции
интерфейса на средства пользовательского ввода — мышь, клавиатуру, перо,
сенсор-
ный экран. Однако при завершении асинхронной операции поток пула завершает
объект
Task
, возобновляя работу конечного автомата.
Для некоторых приложений такое поведение нормально и даже желательно,
потому что оно эффективно. Но для других моделей приложений (например,
приложений с графическим интерфейсом) оно создает проблемы, потому что код
выдает исключение при попытке обновления элементов пользовательского интер-
фейса через поток из пула. Иногда последний должен каким-то образом заставить
графический поток обновлять элементы пользовательского интерфейса.
Приложения ASP.NET позволяют любому потоку делать все, что угодно.
Начав
обрабатывать клиентский запрос, поток пула может выбрать пользовательские
региональные стандарты (
System.Globalization.CultureInfo
), позволив серверу
осуществить принятые в рассматриваемом регионе форматы чисел,
дат и времени
1
.
Также веб-сервер может определить идентификационные данные клиента (
System.
Security.Principal.IPrincipal
), предоставив ему доступ только к тем ресурсам,
на которые у него есть права. Порожденная одним потоком пула асинхронная опе-
рация заканчивается другим потоком, который обрабатывает ее результат. Хотя эта
работа и выполняется по
поручению клиентского запроса, региональные стандарты
и идентификационные данные клиента должны «переходить» к новому потоку пула,
чтобы вся работа, выполняемая по поручению клиента, использовала региональные
стандарты и идентификационную информацию клиента.
К счастью, в FCL определен базовый
класс
System.Threading.Synchronization-
Context
, позволяющий решить все описанные проблемы. Объект, производный от
этого класса, связывает прикладную модель с потоковой. В FCL имеется группа
классов, производных от класса
SynchronizationContext
, но обычно напрямую
они не
используются; более того, многие из них даже не документированы.
В основном разработчикам приложений не нужно ничего знать о клас-
се
SynchronizationContext
. При вызове
await
для
Task
используется объект
SynchronizationContext
вызывающего потока. Когда
пул потока завершает объект
Task
, используется объект
SynchronizationContext
, обеспечивающий соответствие
потоковой и прикладной модели. Таким образом, когда GUI-поток выполняет
await
для
Task
, код,
следующий за оператором
await
, заведомо будет исполнен
в GUI-потоке, что позволяет этому коду обновить элементы пользовательского
1
Дополнительная информация по данной теме находится по адресу http://msdn.microsoft.
com/ru-ru/library/bz9tc508.aspx.