Диспетчер приложений и Диспетчер контроля - PullRequest
3 голосов
/ 26 ноября 2011

Предположим, у меня есть кнопка управления с именем "button1" и функция с именем "doSomething".Функция "doSomething" вызывается из другого потока.

У меня есть два метода для вызова функции doSomething из потока пользовательского интерфейса.

Сначала из диспетчера кнопок управления

this.button1.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));

иВо-вторых, от диспетчера приложений

this.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));

Результат один и тот же, что реально отличается?

Ответы [ 3 ]

5 голосов
/ 26 ноября 2011

На один и тот же экземпляр диспетчера ссылаются все элементы управления, принадлежащие одному и тому же потоку. Разницы нет.

3 голосов
/ 26 ноября 2011

Все элементы управления пользовательского интерфейса (которые были созданы в обычном режиме) совместно используют один и тот же экземпляр диспетчера.Этот диспетчер работает в потоке пользовательского интерфейса.Если вы создадите некоторый элемент управления в потоке backgroud, он создаст новый диспетчер в этом потоке, и это будет не очень хорошо.Лучший способ избежать большинства проблем с многопоточностью и элементами управления пользовательским интерфейсом как в WinForms, так и в WPF - это использовать System.Threading.SynchronizationContext.Current.Рабочий процесс прост: вы получаете System.Threading.SynchronizationContext.Current, находясь в потоке пользовательского интерфейса, и сохраняете его где-нибудь (например, в открытом статическом поле).Затем, когда вы захотите запустить некоторый код в потоке пользовательского интерфейса, вы обращаетесь к сохраненному SynchronizationContext intance и используете его методы Send или Post.Он будет запускать вас делегаты в потоке, где был достигнут SynchronizationContext (для текущего случая в потоке пользовательского интерфейса).Кроме того, он достаточно умен, чтобы использовать текущий способ Invoking (цикл сообщений для WinForms и диспетчер для WPF), а также, если вы уже звоните из потока пользовательского интерфейса, он просто будет синхронно запускать ваш делегат.Просто помните, что вы должны получить SynchronizationContext только после того, как создадите свой первый элемент управления в текущем потоке пользовательского интерфейса, потому что SynchronizationContext будет инициализирован сразу после этого.

0 голосов
/ 19 марта 2018

В большинстве случаев у нас один поток пользовательского интерфейса. Так что, это не имеет значения, что вы звоните

control.Dispatcher(which comes inherited from DispatcherObject parent of the controls).

or 

Disptacher.Current.

Но есть сценарии, в которых у вас будет несколько диспетчеров. Таким образом, в этой ситуации Control.Dispatcher поможет, так как он обнаружит текущего диспетчера для соблюдения Thread Affinity. В этом Dispatcher.Current не поможет.

Один сценарий с выделенным потоком (с диспетчером) для отображения индикатора занятости, поскольку поток пользовательского интерфейса по умолчанию занят рендерингом большого списка элементов управления.

Однако SynchronizationContext - это еще один способ избежать подобных проблем. но что, если этот контекст или поток больше не требуются или он был установлен в null любым другим разработчиком Поэтому, на мой взгляд, всегда разумно использовать Control.Dispatcher.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...