7 Stimmen

Aktualisieren einer ObservableCollection von einem anderen Thread aus

Ich habe versucht, einen Griff auf die Rx-Bibliothek zu bekommen und arbeiten es in WPF mit MVVM aus. Ich brach meine Anwendung in Komponenten wie Repository und das ViewModel. Mein Repository in der Lage, eine Sammlung von Studenten einer nach dem anderen bereitzustellen, aber der Moment, den ich versuche, in die Ansicht gebunden ObservableCollection es wirft einen Thread-Fehler hinzufügen. Ich 'd apreciate einige Zeiger auf, um diese Arbeit für mich zu erhalten.

8voto

Phil Punkte 40767

Sie müssen den Synchronisationskontext korrekt einstellen, indem Sie

ObserveOn(SynchronizationContext.Current)

Siehe diesen Blogbeitrag

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

für ein Beispiel.

Hier ist ein Beispiel, das für mich funktioniert:

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

1voto

Stephen Holt Punkte 2260

Läuft Ihr Code in einem Hintergrund-Thread? Da es die Benutzeroberfläche betrifft, kann eine View-gebundene ObservableCollection nur auf dem UI/Dispatcher-Thread aktualisiert werden.

Siehe WPF ObservableCollection Thread Sicherheit für ein ähnliches Problem.

1voto

Sofian Hnaide Punkte 2246

Alle Änderungen an der Benutzeroberfläche sollten von der Dispatcher Thema. Eine gute Praxis, wenn Sie anthoer Thread ständige Änderung der Ansicht Modell ist zu erzwingen Eigenschaft Setter, um die Dispatcher-Thread verwenden. In diesem Fall stellen Sie sicher, dass Sie nicht ein UI-Element auf einem anderen Thread ändern.

Versuchen Sie es:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X