Dispatcher.CurrentDispatcher проти Application.Current.Dispatcher


78

Які відмінності між Dispatcher.CurrentDispatcherSystem.Windows.Threading) і Application.Current.DispatcherSystem.Windows)?

Мій кишечник каже мені, що Application.Current.Dispatcherніколи не зміниться і є загальним для всіх потоків у поточній програмі, тоді як Dispatcher.CurrentDispatcherможе створити новий екземпляр Dispatcherзалежно від потоку, з якого він був викликаний.

Це правильно?

Якщо це так, то призначення Dispatcher.CurrentDispatcherнасамперед для багатопотокового інтерфейсу?

Відповіді:


98

Мій кишечник повідомляє мені, що Application.Current.Dispatcher ніколи не зміниться і є загальним для всіх потоків у поточній програмі, тоді як Dispatcher.CurrentDispatcher може створити новий екземпляр Dispatcher залежно від потоку, з якого він був викликаний.

Це правильно.

Крім того, немає сенсу взагалі отримувати доступ Dispatcher.CurrentDispatcherіз потоку, що не є UI. Він нічого не зробить, якщо ви не подзвоните Dispatcher.Run, і входження в нескінченний цикл повідомлень - це не те, що ви хочете робити з робочих потоків.

Так:

  • У найпоширенішому сценарії , коли у вашому додатку є лише один потік інтерфейсу користувача, Application.Current.Dispatcherі Dispatcher.CurrentDispatcherвсередині потоку інтерфейсу повертається той самий екземпляр. Який із них ви використовуєте, це просто питання переваг.

  • Якщо у вашому додатку більше одного потоку інтерфейсу, то кожен з DispatcherObjectних буде постійно пов’язаний з диспетчером потоку інтерфейсу, у якому він був створений під час побудови. У цьому випадку Application.Current.Dispatcherбуде посилатися на диспетчера потоку, з якого породжена ваша програма; ви не зможете використовувати його для розміщення повідомлень у елементах керування, що належать вашим іншим потокам інтерфейсу користувача.


2
Дякую за пояснення, але що ви маєте на увазі під словом "Він нічого не зробить, якщо ви не зателефонуєте Dispatcher.Run"? Я використовував CurrentDispatcher із потоку, що не є UI, і Invoke справді викликає делегата. Ви маєте на увазі, що делегатів буде просто викликано у потоці виклику?
ken

2
@ken: Invokeа друзі зазвичай "пакують" (маршал, якщо бажаєте) виклик методу у повідомлення Win32 і відправляє його в чергу повідомлень, з якої цикл повідомлень (цикл диспетчера) з часом витягує його та виконує виклик. Оскільки диспетчерського циклу немає (якщо ви знаходитесь у цьому циклі, ваш код не працював би), дзвінок насправді ніколи не відбудеться. Отже, я припускаю, що Invokeспочатку перевіряє, чи ви вже в CurrentDispatcherпотоці як оптимізація, і чи виконуєте ви виклик на місці, а не маршалинг. Ви можете перевірити це, перевіривши Thread.ManagedThreadId.
Джон,

ви не зможете використовувати його для розміщення повідомлень у елементах керування, що належать вашим іншим потокам інтерфейсу користувача. Отже, скільки потоків інтерфейсу є у вашому середньому додатку WPF?

@Will: Один: "Якщо у вашому додатку є лише один потік інтерфейсу користувача (швидше за все) ..." . Як ви вважаєте, чи потрібно це ще більше уточнювати?
Джон,

1
@Will: Відредаговано для збільшення видимості відповідної частини. Дякую, що повідомив мені.
Джон

21

Простіше кажучи ...

Dispatcher.CurrentDispatcher отримує диспетчер поточного потоку . Отже, якщо ви шукаєте диспетчер потоку інтерфейсу користувача у фоновому процесі, не використовуйте це.

Application.Current.Dispatcher завжди надаватиме вам диспетчер потоку інтерфейсу користувача, оскільки цей потік обертає єдиний екземпляр програми.


9

Мій кишечник повідомляє мені, що Application.Current.Dispatcher ніколи не зміниться і є загальним для всіх потоків у поточній програмі, тоді як Dispatcher.CurrentDispatcher може створити новий екземпляр Dispatcher залежно від потоку, з якого він був викликаний.

Це правильно, Application.Current.Dispatcherє властивістю екземпляра програми, яка при побудові призначається диспетчером поточного потоку. І як документаціяDispatcher.CurrentDispatcher зазначається :

Отримує диспетчер для потоку, який виконується в даний час, і створює новий диспетчер, якщо він ще не пов'язаний з потоком.


Якщо це так, то призначення Dispatcher.CurrentDispatcher в першу чергу для багатопотокового інтерфейсу?

Можливо, я не стикався з жодним використанням отримання диспетчера фонового потоку, оскільки у вас, як правило, немає елементів інтерфейсу, що належать до них, до яких ви можете захотіти відправляти операції.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.