2

У меня есть приложение WPF, которое отображает ObservableCollection. Это около 182 строк, и объект (назовем его PositionLight) внутри коллекции имеет около 70 свойств для отображения.GUI заморожен, когда я обновляю свой ObservableCollection

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

Список преобразуется в ObservableCollection в конструкторе EventArgs, отправленного с событием в GIU.

Проблема заключается в том, даже если я использую BeginInvoke и делегат сделать:

myGUICollection = myEventArgsCollection

графический интерфейс пользователя будет заморожен на 3 до 4 секунд ... Я положил много Console.Writeline, чтобы узнать, где узкое место, но похоже, что замораживание произойдет сразу после того, как оно покинет функцию, вызванную BeginInvoke. Я действительно потерялся здесь.

Я использую 4-ядерный ПК с RAM 2.5Go, поэтому я не думаю, что это проблема с оборудованием.

У вас есть идея?

Некоторый код, чтобы дать вам лучшее представление о вставке в графическом интерфейсе:

public bool myCoreScope_OnCoreCalculationHandler(object myObject, CoreCalculationEventArgs myEventArgs) 
    { 

     foreach (PositionLight item in myEventArgs.MyPositionList) 
     { 
      lv.Dispatcher.BeginInvoke(new DisplayPositionItemCallBack(DisplayPositionItem), DispatcherPriority.Send, new object[] { item }); 
     } 

    } 


    private delegate void DisplayPositionItemCallBack(PositionLight item); 

    private void DisplayPositionItem(PositionLight item) 
    { 
     try 
     { 
      MyPositionList.Remove(MyPositionList.First(position => position.ID== item.ID)); 
     } 
     catch (Exception) 
     { } 
     MyPositionList.Add(item); 
    } 
+0

Опубликовать еще код для анализа – TalentTuner

+0

@saurabh: done. Я принял во внимание то, что сказал Фара, но все же в конечном итоге с тем же временем замораживания – Gregfr

ответ

2

При вызове BeginInvoke вы сортировочных обновление в ObservableCollection на GUI потока, поэтому в то время как расчет может происходить на в отдельном потоке обновление пользовательского интерфейса не происходит. Если вы вызовете дорогостоящее обновление в потоке графического интерфейса пользователя, тогда поток должен будет дождаться завершения этой операции.

Альтернативный подход состоит в том, чтобы выполнить вызов для каждого элемента в коллекции, а не для всей коллекции сразу, что даст время графического интерфейса для обработки других сообщений между обновлениями.

var list = GetCollection(); 
foreach (var item in list) 
{ 
    Dispatcher.BeginInvoke(new Action(() => myGuiCollection.Add(item))); 
} 

Другой вариант вы можете попробовать это установить атрибут ItemsSource связывания данных IsAsync.

<ListBox ItemsSource="{Binding myGuiCollection, IsAsync=True}" /> 
+0

то, что вы говорите, имеет смысл, однако, добавление пункта один за другим означает, что я должен сначала найти старый элемент, удалить его, а затем добавить новый один. Боюсь, что это не ускорит процесс. Я дам ему попробовать в любом случае – Gregfr

+0

GOT IT! Вместо того, чтобы удалять и вставлять новый элемент, я обновляю существующий элемент, один за другим. Похоже, что он использует намного меньше процессора, а графический интерфейс больше не заморожен. Я позволю тектору открывать еще несколько часов, чтобы подтвердить, что он работает правильно. – Gregfr

+0

. О, я думал больше об инициализации коллекции, а не о ее обновлении. Для обновления вещей, связанных с пользовательским интерфейсом, вы должны посмотреть на интерфейс INotifyPropertyChanged. Это лучший способ сделать это. –

Смежные вопросы