2011-12-15 2 views
6

내 wpf 응용 프로그램에서 별도의 스레드를 사용하여 내 viewmodel에서 시간이 많이 걸리는 작업이 호출됩니다. 그러나이 함수는 뷰의 개체에 바인딩 된 뷰 모델의 여러 속성에 액세스합니다. 직접 액세스하려고 시도했는데 UI 스레드가 소유하고 있다는 불만이 없습니다. 스레드간에 직접적으로 사용했을 때의 결과를 알고 싶습니다.별도의 스레드에서 ViewModel 속성에 액세스

+0

당신은'ViewModel'을 변경하거나 그것을 별도의 스레드를 읽고 있습니까? – SliverNinja

+0

그냥 별도의 스레드 – Aks

답변

5

읽기 및 쓰기를 포함한 모든 스레드에서 ViewModel을 자유롭게 사용할 수 있습니다. 한 가지 주요 예외는 컬렉션을 다루는 것입니다. 바인딩은 단순 바인딩처럼 UI 스레드에 자동으로 정렬되지 않으므로 데이터 바인딩 컬렉션이 사용자 인터페이스 스레드에 기록되어야합니다.

그러나 쓰기 작업을 수행하려면 적절한 동기화가 필요합니다. ViewModel은 또 다른 클래스이기 때문에 일반적인 스레드 동기화 문제가 발생합니다.

일반적으로, 대부분의 경우와 약간 다른 방식으로 동기화를 처리하려고합니다. 잠금은 일반적으로 WPF 데이터 바인딩이 객체를 잠그지 않으므로 ViewModel에서 작동하지 않습니다. 따라서 일반적으로 Dispatcher.Invoke/BeginInvoke을 사용하여 ViewModel에서 동기화가 필요할 때 필요에 따라 호출을 다시 사용자 인터페이스 스레드에 마샬링해야합니다. 당신이 당신의 ObservableCollection에 연장 사용하는 경우

+0

예를 들어 VM의 'bool'에 바인딩 된 ToggleButton이있는 경우 그리고 별도의 스레드에서'if (bool)'을하고 있는데, 토글을 설정하는 사용자와 if 조건을 실행하는 사용자간에 충돌이 없도록 여기에서 동기화를 유지하려면 어떻게해야합니까? – Aks

+0

@Aks 아니요. 그런 값을 읽는다면 아무런 문제가 없습니다. 즉, 당신은 아마도 (기술적으로) bool 휘발성 마크해야합니다. 자세한 내용은 다음을 참조하십시오. http://stackoverflow.com/questions/458173/can-ac-sharp-thread-really-cache-a-value-and-ignore-changes-to-that-value-on-ot/458193 # 458193 –

1

일반적인 스레드 안전 문제 외에도 아무런 결과가 없습니다. 일반적으로 VM 적합성에 문제가있는 것은 스레드 선호도가있는 ObservableCollections입니다.

+0

실제로 잠금을 사용했다면 UI 스레드가 중단 될 가능성이 있습니까? – Aks

+0

사실입니다. 그러나 "일반적인 스레드 안전 문제"는 WPF에서 사용하려고 시도하는 잠금 또는 표준 스레드 동기화를 무시하므로 비정상적인 해결 방법이 필요합니다. –

0

, 별도의 스레드에서 업데이트 할 수 있습니다

/// <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; 
관련 문제