2016-07-16 4 views
0

Ich entwickle eine Xamarin Forms-Anwendung, aber ich glaube nicht, dass meine Frage Xamarin-spezifisch ist. Nachdem der Benutzer den PIN-Code eingegeben hat (natürlich nur, wenn der PIN korrekt war), zeige ich ihm die Registerseite. Jede dieser Seiten hat einige Steuerelemente, aber noch wichtiger, sie müssen einige Daten aus dem Internet abrufen, indem sie asynchrone Aufrufe verwenden. Jetzt, da meine Anwendung mehrere Tabs hat, möchte ich alle Daten für jeden von ihnen parallel (nicht-aufeinanderfolgend) abrufen. Was ich bisher umgesetzt werden, ist dies:Wie bereitet man Anwendungsdaten im Hintergrund auf?

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... 
     } 
    } 

während alle RefreshData() und RefreshButtons() sieht wie folgt aus:

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

Jetzt, während dies, ich tun, Recht zu sein scheint sich fragen, ob es eine korrekte Art und Weise, es zu tun, und wenn nicht, was ist?

+1

'GetData()' scheint zu einer Aufgabe. Sie können also einfach auf sein Ergebnis warten, nachdem Sie 'RefreshData' async gemacht haben. Keine Notwendigkeit für eine 'Task.Run()' da imo – lokusking

+1

Die 'GetData()' sieht aus wie eine asynchrone Methode (da Sie das 'Ergebnis' berühren) warum also nicht eigentlich die gesamte Kette richtig async machen und keine Aufgaben herumwerfen? –

+0

Es ist in der Tat async, danke. Übrigens bedeutet das, dass ich 'Device.BeginInvokeOnMainThread' nicht brauche, richtig? – nicks

Antwort

1

es wie folgt tun:

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... 
    } 
} 

Und für die Methoden Methoden aktualisieren:

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  
} 

Als Alternative Dinge beschleunigen Sie könnten die Daten referesh für alle Seiten beginnen soll auf einmal . Wenn das ist, was Sie wollen, ändern InitializeChildren etwas wie folgt aus:

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... 
    } 
} 

Dies wird die Refresh auf allen Seiten auf einmal starten, so können die Netzwerk-Operationen gleichzeitig ausgeführt werden. Die Rückkehr zum UI-Thread nach jedem Aufruf wird weiterhin ausgeführt. Task.WhenAll stellt sicher, dass die Seiten erst nach Abschluss aller Aktualisierungsvorgänge an die Children-Auflistung angehängt werden.

+0

Wie wird das Warten auf Kinderseiten vor dem Hinzufügen zur Seite beschleunigt? – nicks

+0

Auch das Abrufen von Daten, bevor der Benutzer den richtigen Pin zur Verfügung stellt, klingt für mich nicht gut ... Denken Sie, dass es in Ordnung ist? Ist es sicher? – nicks

+1

Ich nehme an, die GetData-Methode macht eine Art von Datenzugriff. Dies bedeutet, dass die anderen Aufgaben bereits beginnen können, wenn die Daten von der Festplatte oder vom Netzwerk geladen werden. Nehmen wir an, dass die Netzwerkanforderung 1 Sekunde dauern würde - dann würde der ursprüngliche Code drei Sekunden dauern, aber die gleichzeitige Version würde nur etwas mehr als eine Sekunde dauern, da alle Anfragen gleichzeitig ausgeführt würden. –

Verwandte Themen