2016-02-19 5 views
0

Я получаю немного странное поведение с помощью мобильного приложения я пишу с помощью Xamarin формы, посылка проста:запирание при навигации страницы с Xamarin формы

  • Перейдите на новую страницу (это происходит асинхронно)
  • Получить некоторые данные (асинхронно, а)
  • Bind данные для просмотра

так как я использую MVVM я не могу подключить в любое из событий страницы (появляются/исчезают/и т.д. .) так что я может только начать извлекать данные из конструктора (плохая идея, я знаю).

Вот где (я думаю) вопрос заключается:

навигатор (работает на UI Thread) асинхронно разрешает вид и ViewModel модели представления не может загружать данные асинхронно из конструктора, так он блокирует Пользовательский интерфейс, пока загрузка не будет выполнена.

И до тех пор, пока ваше сетевое соединение будет достаточно быстрым, вы, возможно, даже не заметите его, но когда это займет слишком много времени, система, похоже, думает, что он находится в тупике и завершается.

Так что я попытался решить эту проблему с помощью

Task.Factory.StartNew(() => { GetData(); }); 

в конструкторе, и это работает около 80% времени, но, как я обнаружил, начиная новую задачу не гарантирует новый Нить.

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

Есть ли чистый способ загрузки данных async с помощью mvvm?

+0

Как правило, вы хотите использовать 'Task.Run()'. Возможно, вам стоит подумать об использовании 'await' и' async' _all the way_. – MickyD

+0

Вы по-прежнему можете использовать специальный метод загрузки данных в VM вместо конструктора! В коде позади вашего представления сделайте 'protected async override void OnAppearing()' и вызовите асинхронный вызов методу загрузки вашего vm внутри него. – Depechie

+0

Как правило, 'async void' - плохая идея, если только это обработчик событий, поскольку неотображенное исключение не будет поймано моей попыткой/catch, но в SynchronizationContext, который был активен, когда была запущена асинхронная пустота (обычно это поток пользовательского интерфейса). Обычно это приводит к необработанному исключению – Tseng

ответ

0

ОК, поэтому я нашел проблему. Это действительно была проблема с сетевым кодом, блокирующим приложение, но поскольку я написал 99% этого проекта, я предположил, что все это использовало мой центральный диспетчер сети.

Я был неправ. Где-то глубоко в недрах кода, в одном из базовых классов, есть немного логики, которая отслеживает и загружает локализацию. Он работает немного, как это:

  • решительность СТРАНИЦЫ
  • решительность ViewModel
  • проверки ViewModel переводы
  • ли я необходимые переводы в памяти?
  • нет? У меня есть они в моем местном db?
  • еще раз нет? Попытка загрузить их с сервера локализации
  • сохранить переводы в db и память и добавить их в viewmodel
  • bind viewmodel для просмотра.

Поскольку мы используем MVVM, было сложно получить перевод вовремя и показать их до того, как остальная часть была загружена (мы не смогли найти способ оповестить пользовательский интерфейс о том, что был изменение в переводах db).

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

В основном это означает, что я потратил большую часть двух дней на перестройку всей логики разрешения разрешений, чтобы работать асинхронно и немного выполнить предварительную выборку переводов (при необходимости).