2012-02-20 34 views
5

Tôi đã cố gắng để có được một xử lý trên thư viện Rx và làm việc nó ra trong WPF với MVVM. Tôi đã phá vỡ ứng dụng của mình thành các thành phần như kho lưu trữ và ViewModel. Kho lưu trữ của tôi trong khả năng cung cấp một bộ sưu tập của sinh viên từng người một nhưng thời điểm tôi cố gắng để thêm vào các Viewable ObservableCollection nó ném một lỗi thread. Tôi muốn một số con trỏ trên để có được điều này làm việc cho tôi.Cập nhật một ObservableCollection từ một chủ đề khác

+0

thể trùng lặp của [Đang cập nhật một ObservableCollection trong một thread riêng biệt] (http://stackoverflow.com/questions/2104614/updating-an-observablecollection-in-a-separate-thread) –

+0

Hãy thử liên kết sau đây cung cấp giải pháp an toàn chủ đề hoạt động từ bất kỳ chuỗi nào và có thể bị ràng buộc bởi nhiều chuỗi giao diện người dùng: http://www.codeproject.com/Articles/64936/Multithreaded-ObservableImmutableCollection – Anthony

Trả lời

8

Bạn cần phải thiết lập bối cảnh đồng bộ hóa một cách chính xác bằng

ObserveOn(SynchronizationContext.Current) 

Xem bài viết trên blog này

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

cho một ví dụ.

Dưới đây là một ví dụ mà làm việc cho tôi:

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

phương pháp này hoạt động nếu mã nằm trong mã Xamls phía sau nhưng tôi cần ViewModel để thêm một thực thể. Nguồn của tôi là một dịch vụ Async được gọi từ một ViewModel. Tại thời điểm đó SynchronitaionContext.Current sẽ không có bất kỳ giá trị trong ViewModel –

+0

Tôi đã thêm một ví dụ mà làm việc cho tôi. Lưu ý rằng tôi đã thêm Rx-Main và Rx-WPF thông qua NuGet. – Phil

+0

Mã của tôi nhiều hơn hoặc ít hơn giống nhau nhưng việc lấy và phân bổ bộ sưu tập của tôi xảy ra trong Constructor. Ngoài ra tôi đang sử dụng Unity để giải quyết lớp học. Tôi đã thêm một mã chi tiết tại đây http://stackoverflow.com/questions/9377290/synchronizationcontext-current-is-null-on-resolving-with-unity-in-wpf –

1

Mã của bạn có đang chạy trên một chuỗi nền không? Vì nó ảnh hưởng đến giao diện người dùng, nên chỉ có thể cập nhật ObservableCollection của Chế độ xem được xem trên luồng giao diện người dùng/Người điều phối.

Xem WPF ObservableCollection Thread Safety cho một vấn đề tương tự.

1

Bất kỳ thay đổi giao diện người dùng nên được thực hiện bởi các chủ đề Dispatcher. Một thực hành tốt nếu bạn có chủ đề anthoer liên tục thay đổi mô hình xem là để buộc các bộ định vị thuộc tính sử dụng luồng điều phối. Trong trường hợp này, bạn chắc chắn rằng bạn sẽ không thay đổi một phần tử giao diện người dùng trên một chủ đề khác.

Hãy thử:

public string Property 
{ 
    set 
    { 
     Dispatcher.BeginInvoke(()=> _property = value) ; 
     OnPropertyChanged("Property"); 
    } 
    get 
    { 
     return _property; 
    } 
} 
Các vấn đề liên quan