2013-11-01 16 views
7

私はこの概念を理解するのに苦労しています。多くの実験の後でさえ、WPFでObservableCollectionsを使用し、BindingOperations.EnableCollectionSynchronizationを使用してベストプラクティスが何であるか把握できません。WPFのBindingOperations.EnableCollectionSynchronizationミステリー

私が観察コレクションとのviewmodelを持っており、以下に示すように、私はロックを使用して、その上にコレクションの同期を有​​効にする場合:

m_obsverableCollection = new ObservableCollection<..>; 
BindingOperations.EnableCollectionSynchronization(m_obsverableCollection, 
                m_obsverableCollectionLock); 

それはその観測可能なコレクションのすべての変更と列挙がなることを意味しています:

  1. m_obsverableCollectionLockを使用して自動的にコレクションをロックしますか?
  2. コレクションが作成されたスレッドのすべての変更をマーシャルしますか?
  3. バインディング操作が呼び出されたスレッドのすべての変更をマーシャルしましたか?

BindingOperations.EnableCollectionSynchronizationを使用する場合、明示的にロックする必要がありますか?

BindingOperations.EnableCollectionSynchronizationを使用し、同じロックを使用してアイテムをロックした後でも、そのメソッドに渡されました。非常に時々、私はを取得します。 "このタイプのCollectionViewは、SourceCollectionの変更をサポートしていませんDispatcherスレッドとは異なるスレッドです。例外

+0

コレクションをどのように変更しようとしているか、どこからどこにコードを投稿することができますか?私は小さなアプリでそれを試して、それは私のために完全に動作します。 –

+0

問題が断続的であったため、コードを再現するための追加ができませんでした。問題は、BindingOperations.EnableSynchronizationをUIスレッド経由で行う必要があることです。そうでなければ、コレクションに非UIスレッド経由でアクセスすると例外がスローされる可能性があります – Ruskin

+0

メインUIスレッドまたはバックグラウンドスレッドでObservableCollectionを更新していますか? bgスレッドからの場合は、 'Application.Current.Dispatcher.BeginInvoke()'への呼び出しを使って更新していますか?あなたは単純な 'lock()'ステートメント(〜sanity)を使ってこの呼び出しを試みましたか? – code4life

答えて

2

は、私は、その特定の構文を使用していないが、私は、バックグラウンドスレッドからObservableCollectionを更新する必要がある時はいつでも、私はこのパターンに従います。

// i just typed this off the top of my head, so be forewarned... :) 
lock(someLockingObj) 
{ 
    Application.Current.Dispatcher.BeginInvoke(new Action(()=> 
    { 
     ... update here.... 
    })); 
} 

通常あなたが遭遇したエラーは場合に発生しますbgスレッドは、Dispatcher.BeginInvoke(またはInvokeもほとんどの場合、IMHOでも動作します)なしでObservableCollectionを直接更新しようとしています。

+0

ありがとう、私は彼らがBindingOperationsクラスを追加しなかったと思うので、それを使って解決しました。 – Ruskin

6

我々は最終的にそれの一番下になった:

私たちは、ディスパッチャにCollectionSynchronizationを有効にする必要があります。

Application.Current.Dispatcher.BeginInvoke(new Action(()=> 
{ 
    BindingOperations.EnableCollectionSynchronization(m_obsverableCollection, m_observableCollectionLock); 
})); 

そして、毎回他のスレッドは、単にあなたができる、観察にアクセスしたい:

lock (m_observableCollectionLock) 
    m_observableCollection.Add(...)