GUI заморожен, пока я обновляю свою коллекцию ObservableCollection - PullRequest
3 голосов
/ 21 октября 2010

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

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

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

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

myGUICollection = myEventArgsCollection

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

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

У вас, ребята, есть идея?

Какой-то код, который даст вам лучшее представление о вставке в GUI:

    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);
    }

1 Ответ

2 голосов
/ 21 октября 2010

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

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

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

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

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