Измените элементы управления WPF из не основного streamа с помощью Dispatcher.Invoke
Я недавно начал программирование в WPF и столкнулся с следующей проблемой. Я не понимаю, как использовать метод Dispatcher.Invoke()
. У меня есть опыт работы с streamами, и я сделал несколько простых программ Windows Forms, где я просто использовал
Control.CheckForIllegalCrossThreadCalls = false;
Да, я знаю, что это очень слабо, но это были простые приложения для мониторинга.
Фактически я делаю приложение WPF, которое извлекает данные в фоновом режиме, я начинаю новый stream, чтобы сделать вызов для извлечения данных (с веб-сервера), теперь я хочу отобразить его в моей форме WPF. Дело в том, что я не могу установить контроль над этим streamом. Даже ярлык или что-то еще. Как это можно решить?
- Задача против различий streamов
- переключатель контекста streamа и переключатель контекста процесса
- Отладка нескольких streamов в eclipse
- Android: RunOnUiThread против AsyncTask
- Вызывающий stream не может получить доступ к этому объекту, потому что ему принадлежит другой stream. WPF
Ответьте на комментарии:
@Jalfp:
Поэтому я использую этот метод Dispatcher в «новом проходе», когда получаю данные? Или я должен заставить фонового работника получить данные, поместить их в поле и запустить новый stream, который ждет, пока это поле будет заполнено, и вызовите диспетчера, чтобы отобразить полученные данные в элементах управления?
- Почему Parallel.ForEach намного быстрее, чем AsParallel (). ForAll (), хотя MSDN предлагает иное?
- stream с несколькими параметрами
- Как использовать wait и уведомлять в Java без IllegalMonitorStateException?
- есть ли в java функция «block until condition станет true»?
- Как мне передать изменяемый объект между streamами?
- Что такое тупик?
- Что такое «stream» (действительно)?
- Почему исключение операции перекрестного streamа не выбрасывается при запуске exe в bin \ Debug
Прежде всего, чтобы понять, что Диспетчер не предназначен для длительной операции блокировки (например, для извлечения данных из WebServer …). Вы можете использовать диспетчер, когда хотите запустить операцию, которая будет выполняться в streamе пользовательского интерфейса (например, обновление значения индикатора выполнения).
Что вы можете сделать, так это получить ваши данные в фоновом работнике и использовать метод ReportProgress для распространения изменений в streamе пользовательского интерфейса.
Если вам действительно нужно напрямую использовать диспетчер, это довольно просто:
Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action(() => this.progressBar.Value = 50));
japf ответил правильно. На всякий случай, если вы смотрите на многострочные действия, вы можете написать, как показано ниже.
Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action(() => { this.progressBar.Value = 50; }));
Информация для других пользователей, которые хотят узнать о производительности:
Если ваш код НЕОБХОДИМО писать для высокой производительности, вы можете сначала проверить, требуется ли вызов с помощью флажка CheckAccess.
if(Application.Current.Dispatcher.CheckAccess()) { this.progressBar.Value = 50; } else { Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action(() => { this.progressBar.Value = 50; })); }
Обратите внимание, что метод CheckAccess () скрыт от Visual Studio 2015, поэтому просто напишите его, не ожидая, что intellisense покажет его. Обратите внимание, что CheckAccess имеет накладные расходы на производительность (накладные расходы за несколько наносекунд). Это лучше, если вы хотите сохранить эту микросекунду, необходимую для выполнения «вызова» любой ценой. Кроме того, всегда существует возможность создать два метода (с вызовом и другими без) при вызове метода, если он находится в streamе пользовательского интерфейса или нет. Это редчайший случай, когда вы должны смотреть на этот аспект диспетчера.