Xamarin Forms: следует ли всегда устанавливать/обновлять ObservableCollection в потоке пользовательского интерфейса?

Недавно мне пришлось реализовать бесконечную прокрутку/ленивую загрузку в моем PCL ListView. Я опущу большую часть кода, но самая важная часть:

Модель представления

   var countries = // get countries
   foreach (var country in countries)
   {
        // Countries is an ObservableCollection<Country> 
        Countries.Add(country);
   }

Казалось, это отлично работает на Android, но на iOS я продолжал получать исключения из диапазона, особенно когда я быстро прокручивал список. Исправление для меня состояло в том, чтобы запустить этот код в основном потоке пользовательского интерфейса.

// wrap the code with this
Device.BeginInvokeOnMainThread(async () => {});

Теперь мой вопрос: должны ли все вызовы службы модели просмотра, которые обновляют или устанавливают наблюдаемую коллекцию, всегда выполняться в потоке пользовательского интерфейса?

У меня есть несколько команд, которые устанавливают Countries. Кажется, они отлично работают без блока потока пользовательского интерфейса. У меня были проблемы только с добавлением элементов, как указано выше.

Следует ли всегда устанавливать и обновлять ObservableCollection в потоке пользовательского интерфейса?


person Mark13426    schedule 04.09.2016    source источник
comment
Действительно, я получил исключение MainThread на iOS при манипулировании ObservableCollection.   -  person Arvis    schedule 28.06.2019


Ответы (1)


Сам ObservableCollection не является потокобезопасным. Однако вы можете изменить свойства ViewModel (среди них ObservableCollections) из потока, отличного от пользовательского интерфейса, поскольку код, обновляющий свойства самих представлений пользовательского интерфейса, будет выполняться в потоке пользовательского интерфейса. Xamarin позаботится об этом сам. Попробуйте использовать потокобезопасную ObservableCollection.

person nicks    schedule 05.09.2016
comment
Спасибо. Если Xamarin обрабатывает переключение потоков, почему я должен использовать потокобезопасную ObservableCollection? - person Mark13426; 07.09.2016
comment
Потому что вы можете изменить его из разных тем. - person nicks; 07.09.2016
comment
гарантируется, что Xamarin будет обновлять объекты пользовательского интерфейса (на основе изменений в виртуальной машине) в потоке пользовательского интерфейса. вам решать обновлять виртуальную машину в том же потоке или использовать потокобезопасные объекты. - person nicks; 07.09.2016
comment
Re Однако вы можете изменить свойства ViewModel (среди них ObservableCollections) из потока, отличного от пользовательского интерфейса, потому что код, обновляющий свойства самих представлений пользовательского интерфейса, будет выполняться в потоке пользовательского интерфейса - для меня это не имеет смысла. Нет, вы не можете невозможно безопасно добавлять/удалять элементы ваших ObservableCollections из фонового потока — если код пользовательского интерфейса находится в середине макета, перечисляя эту коллекцию, и ваш поток получает шанс запуститься, вы получите исключение, измененное коллекцией. Это происходит в моем коде прямо сейчас. Не думайте, что поток пользовательского интерфейса всегда завершает свою задачу перед приостановкой. - person ToolmakerSteve; 18.04.2020