Классы WPF имеют сходство потоков. Это означает, что все изменения этих объектов должны находиться в том же потоке, в котором они были созданы. Действительно трудно создать API-интерфейс пользовательского интерфейса, который поддерживает потоки, поэтому Microsoft решила сохранить его однопоточным и принудительно проверять во время выполнения, чтобы убедиться в этом.
Тем не менее, есть несколько вариантов, которые вы должны выполнить сортировку в фоновом потоке, а затем применить его в потоке пользовательского интерфейса. Первый вариант - скопировать коллекцию SortableCollection в простой старый List или Array и выполнить сортировку в фоновом режиме. Когда фоновый поток завершен, вы используете Dispatcher для выполнения кода в потоке пользовательского интерфейса. Каждый элемент пользовательского интерфейса в WPF расширяется System.Windows.Threading.DispatcherObject
, а большинство - System.Windows.Freezable
. DispatcherObject - это место, где вы получаете 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 и вызываем действие. В этом действии мы назначаем новый отсортированный список обратно нашему объекту.
Ключом к назначению результата любой фоновой работы в потоке пользовательского интерфейса является использование объекта диспетчера пользовательского интерфейса. На самом деле, вероятно, существует полдюжины способов вызова фонового работника в C #, но подход к переносу вашей работы в фоновом потоке в поток пользовательского интерфейса такой же.