Многопоточное, мультидиспетчерское WPF-приложение по-прежнему рисует в одном потоке? - PullRequest
1 голос
/ 18 декабря 2011

У меня есть приложение WPF & C #, которое содержит большую сетку DataGrid, около 35 столбцов х 50 строк, чтобы отслеживать кучу часто меняющихся значений.Беда в том, что когда вся сетка видна, то при ее обновлении пользовательский интерфейс зависает почти на секунду.Я обновляю его явно каждые две секунды, что хорошо для того, что я делаю, но отключение остальной части пользовательского интерфейса - это настоящая боль.

ОК, поэтому я решил запустить остальныепользовательский интерфейс в отдельном окне в отдельном потоке с отдельным диспетчером.Я написал игрушечное окно, содержащее только textBlock с возрастающим счетчиком, который обновляется 10 раз в секунду, используя DispatcherTimer.Однако вместо того, чтобы счетчик плавно увеличивался, он делает паузу, пока сетка обновляется, затем возобновляет отображение со счетом примерно на 10 больше, чем был, когда он приостанавливал , поэтому события таймера обрабатываются.Я просто не вижу обновления.

WPF только рисует все свои элементы в одном потоке?Любой способ обойти это?

Вот мой второй код создания окна:

private void Window_Loaded( object sender, RoutedEventArgs e )
{
    ThreadStart ts = new ThreadStart( RunSpareThread );
    m_spare_thread = new Thread( ts );
    m_spare_thread.IsBackground = true;
    m_spare_thread.Priority = ThreadPriority.Highest;
    m_spare_thread.SetApartmentState( ApartmentState.STA );
    m_spare_thread.Start();

    Dispatcher.Thread.Priority = ThreadPriority.Lowest;
}

void RunSpareThread()
{
    m_spare_window = new SpareWindow();
    m_spare_window.Show();
    Dispatcher.Run();
}

К вашему сведению Я пытался реализовать сетку несколькими различными способами - в виде ListView, как Canvas, который переопределяет OnRenderи рисует целую кучу GlyphRunDrawings - WPF просто невероятно медленно рисует этот материал.

Ответы [ 2 ]

3 голосов
/ 18 декабря 2011

К сожалению, да. Тем не менее, есть несколько вещей, которые вы можете сделать, чтобы повысить отзывчивость вашего интерфейса. Одна из главных вещей - убедиться, что в потоке пользовательского интерфейса выполняется наименьшее количество работы. Это означает выполнение всего чтения БД и т. Д. В отдельном контексте. Вы должны также посмотреть, как ваша сетка отображает ваши значения - это виртуализация? Кроме того, существует также способ привязки данных: источник привязки должен позволять вам обновлять привязку только после того, как все изменения будут завершены.

1 голос
/ 18 декабря 2011

WPF очень быстрый, если вы используете его правильно.

Несколько советов:

  1. Реализация модели (или ViewModel в терминах MVVM) данных, которые вы хотите отобразить. Убедитесь, что он реализует интерфейс INotifyPropertyChanged. Свяжите коллекцию таких моделей со своими DataGrid;
  2. Не обновлять все данные каждые N секунд. Вы должны как-то обнаружить изменения данных (используя рабочий поток) и обновить соответствующие свойства на соответствующих моделях. Из-за привязки данных все изменения будут автоматически отражены в DataGrid. Таким образом, вам даже не нужно использовать Dispatcher (по крайней мере, явно);
  3. Используйте ListView вместо DataGrid, если вам не нужно выполнять специальные действия с данными (например, редактирование, сортировка, фильтрация и т. Д.);
  4. Рассмотрим реализацию виртуализации , если вам нужно отобразить огромное количество строк.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...