Привязка обновления WPF в фоновом потоке

Я имею контроль, которому связали его данные со стандартом ObservableCollection, и у меня есть фоновая задача, которая называет сервис для получения большего количества данных.

Я хочу, затем, обновите мои данные поддержки позади моего управления при отображении, "ожидайте" диалоговое окно, но когда я добавляю новые объекты к набору, поток UI запирается, в то время как это снова переплетает и обновляет мои средства управления.

Я могу обойти это так, чтобы мои анимации и материал продолжали бежать на мой, "ожидайте" диалоговое окно?

Или, по крайней мере, дайте "появление" пользователю что не запертый?

17
задан Mark 24 March 2010 в 05:13
поделиться

4 ответа

Если я правильно понимаю, вы уже используете BackgroundWorker для получения данных, и простое присвоение этих данных ObservableCollection блокирует UI.

Один из способов избежать блокировки пользовательского интерфейса - назначить данные ObservableCollection меньшими порциями, поставив в очередь несколько методов диспетчера. Между каждым вызовом метода могут обрабатываться события пользовательского интерфейса.

следующее будет добавлять по одному элементу за раз, это немного экстремально, но это иллюстрирует концепцию.

void UpdateItems()
{
    //retrievedItems is the data you received from the service
    foreach(object item in retrievedItems)
        Dispatcher.BeginInvoke(DispatcherPriority.Background, new ParameterizedThreadStart(AddItem), item);    
}

void AddItem(object item)
{
    observableCollection.Add(item);
}
18
ответ дан 30 November 2019 в 12:50
поделиться

используйте BackgroundWorker для выполнения этой задачи. обновите коллекцию obsrvablecollection в методе DoWork

0
ответ дан 30 November 2019 в 12:50
поделиться

ObservableCollection будет вызывать события CollectionChanged, которые заставят UI перепривязать данные, измерить, расположить и перерисовать. Это может занять много времени, если у вас много обновлений.

Можно заставить пользователя думать, что UI жив, разделив работу на небольшие пакеты. Используйте диспетчер из потока UI (любой элемент управления имеет ссылку на него) для планирования действий по обновлению коллекции из 10-100 элементов (определите число экспериментальным путем, это просто для поддержки идеи).

Ваш фоновый код может выглядеть так:

void WorkInBackground()
{
    var results = new List<object>();

    //get results...

    // feed UI in packages no more than 100 items
    while (results.Count > 0)
    {
        Application.Current.MainWindow.Dispatcher.BeginInvoke(
            new Action<List<object>>(FeedUI),
            DispatcherPriority.Background,
            results.GetRange(0, Math.Min(results.Count, 100)));
        results.RemoveRange(0, Math.Min(results.Count, 100));
    }
}
void FeedUI(List<object> items)
{
    // items.Count must be small enough to keep UI looks alive
    foreach (var item in items)
    {
        MyCollection.Add(item);
    }
}
10
ответ дан 30 November 2019 в 12:50
поделиться

Используйте это:


Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Render, new Action(UpdateData), value);

private void UpdateData(int value)
{
  BindingSourceProperty = value;
}


-1
ответ дан 30 November 2019 в 12:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: