WPF類具有線程關聯性。這意味着對這些對象的所有更改必須位於創建它們的同一個線程中。創建一個線程安全的用戶界面API確實很難,所以微軟選擇保持它的單線程並強制運行時檢查以確保它。
也就是說,有幾個選項需要在後臺線程中執行排序,然後將其應用於UI線程中。第一個選項是將您的SortableCollection複製到一個普通的舊List或Array中,並在後臺執行排序。一旦後臺線程完成,您就可以使用Dispatcher在UI線程中執行代碼。 WPF中的每個UI元素都延伸System.Windows.Threading.DispatcherObject
,大部分延伸System.Windows.Freezable
。 DispatcherObject是讓Dispatcher在UI線程中執行代碼的地方。
從邏輯上講,執行將是這樣的:
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線程中的方法是相同的。
感謝Berin的解釋, 但是,我必須把這種方法? 在SortableCollection中或者在處理排序方法的事件處理程序中? – Khaldoun 2010-12-21 14:21:05
無論它對你來說最合理的邏輯。在SortableCollection中做這件事的好處是你可以將SortableCollection傳遞給不同的方法,並且它們可以自動與它進行交互。請注意警告:調度程序是一項昂貴的操作。偶爾可以調用它,但是在一個緊密的循環中它會減慢速度。 – 2010-12-21 14:38:47