Как создать observableCollection Сортируемая и многопоточность - PullRequest
0 голосов
/ 20 декабря 2010

Вот моя проблема, я создал SortableCollection: ObservableCollection и добавил метод сортировки (сортировка цветов).Когда я сортирую коллекцию с основным потоком, она работает, все в порядке и работает. Но когда я пытаюсь отсортировать этот customCollection с использованием элемента в коллекции, у меня есть исключение: (Вызывающий поток не может получить доступ к этому объекту, потому что другой потоквладеет им).Я посмотрел в Интернете, и я нашел несколько решений, Одно решение

Этот тип решения положить многопоточность коллекции для вставки, удаление операции перемещения.Но не для пользовательской сортировки.Спасибо за помощь,

1 Ответ

0 голосов
/ 20 декабря 2010

Классы 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 #, но подход к переносу вашей работы в фоновом потоке в поток пользовательского интерфейса такой же.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...