Обновление ObservableCollection из другого потока

Я пытался получить дескриптор библиотеки Rx и работать в WPF с MVVM. Я разбил свое приложение на такие компоненты, как репозиторий и ViewModel. Мой репозиторий в состоянии предоставить коллекцию студентов один за другим, но в тот момент, когда я пытаюсь добавить в View bound ObservableCollection, он выдает ошибку потока. Я бы оценил какой-то указатель, чтобы заставить это работать на меня.

3 ответов


вам нужно правильно установить контекст синхронизации, используя

ObserveOn(SynchronizationContext.Current)

см. это сообщение в блоге

http://10rem.net/blog/2011/02/17/asynchronous-web-and-network-calls-on-the-client-in-wpf-and-silverlight-and-net-in-general

для примера.

вот пример, который работает для меня:

<Page.Resources>
    <ViewModel:ReactiveListViewModel x:Key="model"/>
</Page.Resources>

<Grid DataContext="{StaticResource model}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Button Content="Start" Command="{Binding StartCommand}"/>
    <ListBox ItemsSource="{Binding Items}" Grid.Row="1"/>
</Grid>

public class ReactiveListViewModel : ViewModelBase
{
    public ReactiveListViewModel()
    {
        Items = new ObservableCollection<long>();
        StartCommand = new RelayCommand(Start);
    }

    public ICommand StartCommand { get; private set; }

    private void Start()
    {
        var observable = Observable.Interval(TimeSpan.FromSeconds(1));

        //Exception: This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.
        //observable.Subscribe(num => Items.Add(num));

        // Works fine
        observable.ObserveOn(SynchronizationContext.Current).Subscribe(num => Items.Add(num));

        // Works fine
        //observable.ObserveOnDispatcher().Subscribe(num => Items.Add(num));
    }

    public ObservableCollection<long> Items { get; private set; }
}

выполняется ли ваш код в фоновом потоке? Поскольку это влияет на пользовательский интерфейс, ObservableCollection с привязкой представления может быть обновлен только в потоке UI/Dispatcher.

посмотреть WPF ObservableCollection безопасность потока для подобной проблеме.


любое изменение пользовательского интерфейса должно быть сделано Dispatcher нить. Хорошей практикой, если у вас есть поток anthoer, постоянно меняющий модель представления, является принудительное использование потока диспетчера. В этом случае вы убедитесь, что не измените элемент пользовательского интерфейса в другом потоке.

попробуй:

public string Property 
{ 
   set 
    { 
      Dispatcher.BeginInvoke(()=> _property = value ) ; 
      OnPropertyChanged("Property");  
    } 
   get 
    { 
      return _property; 
    }
}