10

これが私が持っているものです - ItemsSource が a に設定された ListBox ObservableCollection<T> - ここで、T はファイルを表すカスタム クラスで、Filename と ThumbnailPath の 2 つの DependencyProperties だけを含みます。- リストボックスには、その下に画像とファイル名を適切に表示するために、カスタム DataTemplate も定義されています。

リストボックスの目的は、現在のフォルダー (TreeView で選択されている) 内のビデオ ファイルを、サムネイル (非同期的に生成されます。この問題の一部ではありません) と共に表示することです。

したがって、TreeView のフォルダーを変更すると、ObservableCollection がクリアされて再びいっぱいになり、ListBox アイテムに自動的に反映されます。

問題は次のとおりです。UI が応答しなくなり、更新に数秒かかります。ここでも、サムネイルは重要ではありません (無効にしてみました)。 最も時間がかかるのは、カスタム クラスの 50 ~ 100 個のインスタンスの構築と、それらの視覚的表現です。それぞれの Image オブジェクトを初期化する必要がありますしかし、それは私の推測にすぎません。その可能性を確認または除外していただけますか?

ObservableCollection はここに行く方法ではないかもしれないと考え始めています。私が読んだことと私が試したことから、少なくともこれらのアイテムが DependencyObjects である場合、アイテムを非同期的に追加する方法がないからです。BackgroundWorker を使用してクラス インスタンスを作成し、それらを ProgressChanged イベント ハンドラーのコレクションに追加しようとしましたが、例外がスローされます (スレッド化と依存オブジェクトの問題)。

私が見逃しているものはありますか?それとも、単に ObservableCollection を捨てて、古き良き async for ループを記述して項目を追加する方がよいのでしょうか?

4

3 に答える 3

19

あなたObservableCollectionはUIにバインドされているため、UIスレッドで生成されるため、それ以降の更新(削除/追加/クリア)は同じUIスレッドで行う必要があります。別のスレッドからの更新は許可されません。

ただし、できることは、クラスのインスタンス (またはバックグラウンド スレッドでのすべての時間のかかる操作) を作成し、完了したら、次Dispatcherのように UI スレッドを使用して ObservableCollection にオブジェクトを追加することです。

App.Current.Dispatcher.BeginInvoke((Action)delegate()
                          {
                              observableCollection.Add(instanceOfYourClass);
                          });

Dispatcherが行うことは、関連付けられたスレッドに操作を配置することです。したがって、アイテムは常に UI スレッドで追加されますが、バックグラウンド スレッドで作成できます。

ここにいくつかのリンクがあります - Updating from BW and the other one is here

于 2012-10-14T10:53:33.423 に答える
11

.net 4.5 では、EnableCollectionSynchronization を使用できます

 object lockObj = new object();
        BindingOperations.EnableCollectionSynchronization(yourObservableCollection, lockObj);
于 2016-07-01T14:38:51.153 に答える