2016-07-16 3 views
0

Я разрабатываю приложение Xamarin Forms, но я не думаю, что мой вопрос задан Xamarin. После того, как пользователь вводит пин-код (конечно, только если PIN-код правильный), я покажу ему вкладку. На каждой из этих страниц есть некоторые элементы управления, но что более важно, каждый из них должен извлекать некоторые данные из Интернета, используя асинхронные вызовы. Теперь, поскольку мое приложение имеет несколько вкладок, я хочу получить все данные для каждого из них параллельно (не последовательно). Что я реализовал до сих пор, это:Как подготовить данные приложения в фоновом режиме?

public MainTabbedPage(bool requirePin) 
    { 
     if (requirePin) 
     { 
      Navigation.PushModalAsync(new PinEntryPage(this)); 
     } 
     InitializeComponent(); 

    } 

    public void InitializeChildren() 
    { 
     try 
     { 
      var page1 = new Page1(); 
      page1.RefreshData(); 

      var page2 = new Page2(); 
      page2.RefreshButtons(); 
      page2.RefreshData(); 

      var page3 = new Page3(); 
      page3.RefreshData(); 

      Children.Add(page1); 
      Children.Add(page2); 
      Children.Add(page3); 
     } 
     catch (Exception ex) 
     { 
      // some error handling... 
     } 
    } 

пока все RefreshData() и RefreshButtons() выглядеть следующим образом:

public void RefreshData() 
    { 
     Task.Run(
      () => 
      { 
       var data = ApiSingleton.Instance.GetData().Result; 
       // some data manipulations 
       Device.BeginInvokeOnMainThread(() => /* some UI manipulation*/); 
       } 
      }); 
    } 

Теперь, в то время как это, кажется, делает правильно, интересно, если это правильно способ сделать это, а если нет, то что?

+1

'GetData()' похоже на задачу. Таким образом, вы можете просто ждать его результата после создания асинхронизации 'RefreshData'. Нет необходимости в 'Task.Run()' there imo – lokusking

+1

'GetData()' выглядит как метод async (так как вы касаетесь 'Result'), так почему бы не сделать всю цепочку правильно асинхронной, а не бросать задачи? –

+0

Это асинхронно, спасибо. Кстати, это означает, что мне не нужно 'Device.BeginInvokeOnMainThread', правильно? – nicks

ответ

1

Делают это так:

public MainTabbedPage(bool requirePin) 
{ 
    if (requirePin) 
    { 
     Navigation.PushModalAsync(new PinEntryPage(this)); 
    } 
    InitializeComponent(); 
} 

public async void InitializeChildren() 
{ 
    try 
    { 
     var page1 = new Page1(); 
     await page1.RefreshData(); 

     var page2 = new Page2(); 
     await page2.RefreshButtons(); 
     await page2.RefreshData(); 

     var page3 = new Page3(); 
     await page3.RefreshData(); 

     Children.Add(page1); 
     Children.Add(page2); 
     Children.Add(page3); 
    } 
    catch (Exception ex) 
    { 
     // some error handling... 
    } 
} 

И для методов обновления методов:

public async Task RefreshData() 
{ 
    var data = await ApiSingleton.Instance.GetData(); 
    // some data manipulations 
    // you are on the UI thread here 
    // so there is no nead for BeginInvokeOnMainThread  
} 

В качестве альтернативы, чтобы ускорить вещи вы можете начать referesh данных для всех страниц сразу , Если это то, что вы хотите, изменить InitializeChildren к чему-то вроде этого:

public async void InitializeChildren() 
{ 
    try 
    { 
     var page1 = new Page1(); 
     var refreshPage1Task = page1.RefreshData(); 

     var page2 = new Page2(); 
     var refreshButtonsPage2Task = page2.RefreshButtons(); 
     var refreshPage2Task = page2.RefreshData(); 

     var page3 = new Page3(); 
     var refreshPage3Task = page3.RefreshData(); 

     await Task.WhenAll(new Task[] { 
      refreshPage1Task, refreshPage2Task, 
      refreshPage3Task, refreshButtonsPage2Task }); 

     Children.Add(page1); 
     Children.Add(page2); 
     Children.Add(page3); 
    } 
    catch (Exception ex) 
    { 
     // some error handling... 
    } 
} 

Это запустит обновление на всех страницах сразу, поэтому сетевые операции могут выполняться одновременно. Возврат к потоку пользовательского интерфейса после каждого вызова будет продолжаться. Task.WhenAll гарантирует, что страницы будут добавлены к коллекции Children только после завершения всех операций обновления.

+0

Как ожидание инициализации страниц для детей, прежде чем добавлять их на страницу, ускорит процесс? – nicks

+0

Кроме того, начальная выборка данных до того, как пользователь предоставит правильный штырь, не звучит хорошо для меня ... Как вы думаете, все в порядке? Это безопасно? – nicks

+1

Я полагаю, что метод GetData делает какой-то доступ к данным. Это означает, что когда данные загружаются с диска или из сети, другие задачи могут уже начаться. Предположим, что запрос сети займет 1 секунду - тогда исходный код займет три секунды, но параллельная версия займет немного меньше одной секунды, потому что все запросы будут выполняться в одно и то же время. –