Как написать провальный тест на сродство потоков ObservableCollections - PullRequest
2 голосов
/ 27 января 2012

У меня есть потокобезопасная замена наблюдаемой коллекции, для которой я хотел бы написать модульный тест.Чтобы избежать ложных срабатываний, я пытаюсь написать многопоточный тест, который доказывает, что объект не может быть добавлен в ObservableCollection <> без сбоев, поэтому я могу поменять его с моим и смотреть, как он становится зеленым.Я просто не могу заставить этот тест потерпеть неудачу (используя NUnit).

Ни в каком конкретном порядке я до сих пор не пытался:

  • Создание коллекции в другом потоке и обновление в текущем
  • Создание коллекции в текущем потоке и обновление в альтернативном
  • Использование различных механизмов потоков
    • ThreadStart
    • Диспетчер
    • BackgroundWorker
  • Использование разных состояний квартиры
    • Все комбинации STA и MTA на самом тесте и / или один или оба потока
  • Создание окна WPF для хранения коллекции и ручного управления кадрами Dispatcher для имитации среды выполнения.

Сама пользовательская коллекция отлично работает в реальном коде, так что теперь это скорее академическое упражнениечем что-либо;Моя уверенность в потоке была потрясена:)

1 Ответ

4 голосов
/ 27 января 2012

Вы пытаетесь протестировать что-то, чего нет ...

Нет причин для того, чтобы этот тест не прошел, потому что сам класс ObservableCollection<T> не имеет привязки к потоку .Это не потокобезопасно, но просто означает, что поведение будет непредсказуемым, если вы используете его в многопоточном сценарии без надлежащей блокировки;в ObservableCollection<T> нет ничего, что явным образом сгенерирует исключение, если вы сделаете это.

Однако CollectionView класс имеет сходство потоков, поэтомуневозможно добавить элементы в ObservableCollection<T> из другого потока , если к нему прикреплен CollectionView (что происходит, например, когда вы связываете ItemsControl с коллекцией).Но CollectionView вызывает исключение, а не ObservableCollection<T> ...

Возьмите следующий код:

var list = new ObservableCollection<string>();
// var view = CollectionViewSource.GetDefaultView(list);
ThreadPool.QueueUserWorkItem(_ => list.Add("foo"));

Он выполняется без исключения, но если вы раскомментируетестрока, которая создает CollectionView, выдает NotSupportedException:

Этот тип CollectionView не поддерживает изменения в его SourceCollection из потока, отличного от потока Dispatcher.

...