WPFクラスにはスレッド親和性があります。つまり、これらのオブジェクトへのすべての変更は、作成された同じスレッド内になければなりません。スレッドセーフであるユーザーインターフェイスAPIを作成することは本当に難しいため、マイクロソフトではスレッドをシングルスレッドにして、実行時のチェックを強制してそのことを確認しました。
つまり、バックグラウンドスレッドでソートを実行してUIスレッドで適用する必要があるというオプションがいくつかあります。最初のオプションは、SortableCollectionを普通の古いリストまたは配列にコピーし、バックグラウンドでソートを実行することです。バックグラウンドスレッドが完了したら、Dispatcherを使用してUIスレッドでコードを実行します。 WPFのすべてのUI要素はSystem.Windows.Threading.DispatcherObject
を拡張し、ほとんどの要素はSystem.Windows.Freezable
です。 DispatcherObjectは、UIスレッドでコードを実行するDispatcherを取得する場所です。
論理的には、実行はこのようなものになるだろう:
public void BackgroundSort()
{
List<T> items = new List<T>(this.ToArray());
BackgroundSortDelegate del = Sort;
del.BeginInvoke(SortCompleted, del);
}
private void SortCompleted(IAsyncResult result)
{
BackgroundSortDelegate del = result.AsyncState as BackgroundSortDelegate;
List<T> items = del.EndInvoke(result);
this.Dispatcher.Invoke(()=>{this.Collection = items;});
}
何が起こったかの短い説明が背景労働者/代理人は、このリスト内の項目のコピーを使用していることです。ソートが完了したら、Dispatcherオブジェクトを呼び出してアクションを呼び出します。そのアクションでは、新しいソート済みリストをオブジェクトに戻します。
UIスレッド内のバックグラウンド作業の結果を割り当てるためのキーは、UIのDispatcherオブジェクトを使用することです。実際にはC#でバックグラウンドワーカーを呼び出す方法はおそらく半ダンスですが、バックグラウンドスレッドでUIスレッドに作業を取り入れるアプローチは同じです。
説明ありがとうございました、 しかし、私はこのメソッドを置く必要がありますか? SortableCollection、またはソートメソッドを宣言するイベントハンドラでは? – Khaldoun
あなたが論理的に最も理にかなっているところはどこにでもあります。 SortableCollectionでそれを行う利点は、SortableCollectionだけをさまざまなメソッドに渡すことができ、自動的にそのメソッドとやり取りできることです。警告の注記:Dispatcherは高価な操作です。それはときどき呼び出されても問題ありませんが、タイトなループでは実際には遅くなります。 –