2011-12-15 23 views
6

Trong ứng dụng wpf của tôi, hoạt động tốn thời gian trong viewmodel của tôi được gọi bằng cách sử dụng một luồng riêng biệt. Tuy nhiên, hàm này truy cập một số thuộc tính trong khung nhìn được gắn với các đối tượng trong khung nhìn. Tôi đã thử truy cập chúng trực tiếp và tôi thấy không có khiếu nại về chúng được sở hữu bởi các chủ đề giao diện người dùng. Tôi quan tâm đến việc biết hậu quả của việc sử dụng chúng trực tiếp giữa các chủ đề.Truy cập các thuộc tính ViewModel từ chủ đề riêng biệt

+0

Bạn đang chuyển 'ViewModel' hoặc chỉ đọc nó đề riêng biệt? – SliverNinja

+0

chỉ là các chủ đề riêng biệt – Aks

Trả lời

5

Bạn được tự do sử dụng ViewModel của mình từ bất kỳ chủ đề nào - bao gồm đọc và viết. Ngoại lệ chính là giao dịch với các bộ sưu tập - các bộ sưu tập dữ liệu bị ràng buộc phải được ghi vào chủ đề giao diện người dùng, vì ràng buộc không tự động so sánh với luồng giao diện người dùng (như các ràng buộc đơn giản).

Tuy nhiên, bạn vẫn nên cân nhắc việc có đồng bộ hóa phù hợp tại chỗ cho mọi lần viết. Các vấn đề đồng bộ hóa luồng thông thường sẽ xảy ra, vì ViewModel chỉ là một lớp khác.

Điều đó đang được nói, thông thường, bạn sẽ muốn xử lý đồng bộ hóa hơi khác với bạn trong nhiều trường hợp. Ổ khóa thường không hoạt động trên ViewModel, vì ràng buộc dữ liệu WPF sẽ không khóa các đối tượng. Như vậy, bạn thường nên sử dụng Dispatcher.Invoke/BeginInvoke để sắp xếp lại cuộc gọi trở lại luồng giao diện người dùng khi cần khi đồng bộ hóa được yêu cầu trong ViewModel.

+0

Ví dụ: nếu tôi có 'ToggleButton' được liên kết với' bool' trong VM. Và tôi đang làm một 'if (bool)' trong một chuỗi riêng biệt, tôi sẽ phải làm gì để duy trì đồng bộ hóa ở đây để không có xung đột giữa người dùng thiết lập chuyển đổi và nếu điều kiện thực hiện. – Aks

+0

@Aks No. Nếu bạn chỉ đọc một giá trị như vậy, bạn sẽ không gặp vấn đề gì. Điều đó đang được nói, có lẽ bạn nên (kỹ thuật) đánh dấu bool dễ bay hơi. Để biết chi tiết, hãy xem: http://stackoverflow.com/questions/458173/can-ac-sharp-thread-really-cache-a-value-and-ignore-changes-to-that-value-on-ot/458193 # 458193 –

1

Không có hậu quả nào ngoài những lo ngại về an toàn chủ đề thông thường của bạn. Điều duy nhất thường gặp sự cố với các mức độ phù hợp của VM là ObservableCollections có mối quan hệ luồng.

+0

Nếu tôi thực sự sử dụng khóa, không phải là chuỗi giao diện người dùng bị treo? – Aks

+0

Điều này đúng - nhưng "mối quan tâm an toàn chủ đề thông thường" có xu hướng yêu cầu cách giải quyết khác thường, vì WPF sẽ bỏ qua bất kỳ khóa hoặc đồng bộ hóa chuỗi tiêu chuẩn nào bạn cố gắng sử dụng. –

0

Nếu bạn sử dụng mở rộng ObservableCollection của bạn với điều này, bạn có thể cập nhật từ một thread riêng biệt:

/// <summary> 
/// Source: New Things I Learned 
/// Title: Have worker thread update ObservableCollection that is bound to a ListCollectionView 
/// http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx 
/// Note: Improved for clarity and the following of proper coding standards. 
/// </summary> 
/// <param name="e"></param> 
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
{ 
    // Use BlockReentrancy 
    using (BlockReentrancy()) 
    { 
     var eventHandler = CollectionChanged; 

     // Only proceed if handler exists. 
     if (eventHandler != null) 
     { 
      Delegate[] delegates = eventHandler.GetInvocationList(); 

      // Walk thru invocation list 
      foreach (NotifyCollectionChangedEventHandler handler in delegates) 
      { 
       var currentDispatcher = handler.Target as DispatcherObject; 

       // If the subscriber is a DispatcherObject and different thread 
       if ((currentDispatcher != null) && 
        (currentDispatcher.CheckAccess() == false)) 
       { 
        // Invoke handler in the target dispatcher's thread 
        currentDispatcher.Dispatcher.Invoke(
         DispatcherPriority.DataBind, handler, this, e); 
       } 

       else 
       { 
        handler(this, e); 
       } 
      } 
     } 
    } 
} 

/// <summary> 
/// Overridden NotifyCollectionChangedEventHandler event. 
/// </summary> 
public override event NotifyCollectionChangedEventHandler CollectionChanged; 
Các vấn đề liên quan