Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Erstellen Sie UWP-Apps (Universelle Windows-Plattform) mit optimalen Startzeiten, indem Sie die Art und Weise verbessern, wie Sie die Start- und Aktivierung behandeln.
Bewährte Methoden für die Startleistung Ihrer App
Benutzer nehmen teilweise wahr, ob Ihre App schnell oder langsam ist, je nachdem, wie lange das Starten dauert. Für die Zwecke dieses Themas beginnt die Startzeit einer App, wenn der Benutzer die App startet, und endet, wenn der Benutzer auf sinnvolle Weise mit der App interagieren kann. Dieser Abschnitt enthält Vorschläge, wie Sie beim Start ihrer App eine bessere Leistung erzielen können.
Messen der Startzeit Ihrer App
Achten Sie darauf, ihre App ein paar Mal zu starten, bevor Sie die Startzeit messen. Dadurch erhalten Sie eine Grundlage für Ihre Messung und stellen sicher, dass Sie eine möglichst kurze Startzeit messen.
Wenn Ihre UWP-App auf den Computern Ihrer Kunden eintrifft, wurde Ihre App mit der .NET Native-Toolkette kompiliert. .NET Native ist eine Technologie zur Vorauskompilierung, die MSIL in nativ ausführbaren Maschinencode konvertiert. .NET Native-Apps starten schneller, verwenden weniger Arbeitsspeicher und verwenden weniger Akku als ihre MSIL-Entsprechungen. Anwendungen, die mit .NET Native entwickelt wurden, verknüpfen statisch eine benutzerdefinierte Laufzeit und das neue konvergierte .NET Core, das auf allen Geräten ausgeführt werden kann. Dadurch sind sie nicht von der integrierten .NET-Implementierung abhängig. Auf Ihrem Entwicklungscomputer verwendet Ihre App standardmäßig .NET Native, wenn Sie sie im Modus "Release" erstellen, und sie verwendet CoreCLR, wenn Sie sie im Modus "Debuggen" erstellen. Sie können dies in Visual Studio über die Seite "Build" in "Eigenschaften" (C#) oder "Kompilieren">"Erweitert" in "Mein Projekt" (VB) konfigurieren. Suchen Sie nach einem Kontrollkästchen mit der Meldung "Kompilieren mit .NET Native Toolchain".
Natürlich sollten Sie Messungen durchführen, die für das, was der Endbenutzer erleben wird, repräsentativ sind. Wenn Sie also nicht sicher sind, ob Sie Ihre App auf Ihrem Entwicklungscomputer in systemeigenen Code kompilieren, können Sie das Tool Native Image Generator (Ngen.exe) ausführen, um Ihre App vor dem Messen der Startzeit vorzuprekompilieren.
Im folgenden Verfahren wird beschrieben, wie Sie Ngen.exe ausführen, um Ihre App vorab zu kompilieren.
Ausführen von Ngen.exe
Führen Sie Ihre App mindestens einmal aus, um sicherzustellen, dass Ngen.exe sie erkennt.
Öffnen Sie die Aufgabenplanung, indem Sie eine der folgenden Aktionen ausführen:
- Suchen Sie auf dem Startbildschirm nach "Task scheduler".
- Führen Sie "taskschd.msc" aus.
Im linken Bereich des Aufgabenplanerserweitern Sie die Aufgabenplanungsbibliothek.
Erweitern Sie Microsoft.
Erweitern Sie Windows.
Wählen Sie .NET Frameworkaus.
Wählen Sie .NET Framework NGEN 4.x aus der Aufgabenliste aus.
Wenn Sie einen 64-Bit-Computer verwenden, gibt es auch ein .NET Framework NGEN v4.x 64. Wenn Sie eine 64-Bit-App erstellen, wählen Sie .NET Framework NGEN v4.x 64.
Klicken Sie im Menü Aktion auf Ausführen.
Ngen.exe kompiliert alle auf dem Computer verwendeten Apps vor, die keine systemeigenen Images haben. Wenn es viele Apps gibt, die vorkompiliert werden müssen, kann dies eine lange Zeit dauern, aber nachfolgende Ausführungen sind viel schneller.
Wenn Sie Ihre App neu kompilieren, wird das systemeigene Bild nicht mehr verwendet. Stattdessen wird die App just-in-time kompiliert, was bedeutet, dass sie während der Ausführung der App kompiliert wird. Sie müssen Ngen.exe erneut ausführen, um ein neues nativer Image zu erhalten.
Die Arbeit so lange wie möglich aufschieben
Um die Startzeit Ihrer App zu verbessern, müssen Sie nur die Arbeit ausführen, die unbedingt erforderlich ist, damit der Benutzer mit der Interaktion mit der App beginnen kann. Dies kann besonders nützlich sein, wenn Sie das Laden zusätzlicher Assemblys verzögern können. Die Common Language Runtime lädt eine Assembly, wenn sie zum ersten Mal verwendet wird. Wenn Sie die Anzahl der geladenen Assemblys minimieren können, können Sie möglicherweise die Startzeit Und den Speicherverbrauch Ihrer App verbessern.
Länger laufende Arbeiten eigenständig ausführen
Ihre App kann interaktiv sein, obwohl Teile der App nicht voll funktionsfähig sind. Wenn Ihre App beispielsweise Daten anzeigt, die eine Weile zum Abrufen dauern, können Sie diesen Code unabhängig vom Startcode der App ausführen, indem Sie die Daten asynchron abrufen. Wenn die Daten verfügbar sind, füllen Sie die Benutzeroberfläche der App mit den Daten auf.
Viele der UWP-APIs (Universelle Windows-Plattform), die Daten abrufen, sind asynchron, sodass Sie daten wahrscheinlich trotzdem asynchron abrufen. Weitere Informationen zu asynchronen APIs finden Sie unter Aufrufen von asynchronen APIs in C# oder Visual Basic. Wenn Sie Arbeit haben, die keine asynchronen APIs verwendet, können Sie die Task-Klasse verwenden, um lang andauernde Arbeit auszuführen, sodass Sie den Benutzer nicht daran hindern, mit der App zu interagieren. Dadurch bleibt Ihre App reaktionsfähig, während die Daten geladen werden.
Wenn Ihre App eine besonders lange Zeit benötigt, um einen Teil der Benutzeroberfläche zu laden, sollten Sie eine Zeichenfolge in diesem Bereich hinzufügen, die etwa "Abrufen der neuesten Daten" lautet, damit Ihre Benutzer wissen, dass die App noch verarbeitet wird.
Minimieren der Startzeit
Alle außer den einfachsten Apps erfordern eine spürbare Zeit zum Laden von Ressourcen, Parsen von XAML, Einrichten von Datenstrukturen und Logik beim Start ausführen. Hier analysieren wir den Aktivierungsprozess, indem wir ihn in drei Phasen unterteilen. Darüber hinaus bieten wir Tipps zum Verringern der in jeder Phase aufgewendeten Zeit und Techniken, mit denen die einzelnen Phasen des App-Starts für den Benutzer attraktiver werden können.
Der Aktivierungszeitraum ist der Zeitraum zwischen dem Zeitpunkt, zu dem ein Benutzer die App startet, und dem Moment, in dem die App funktionsfähig ist. Dies ist ein wichtiger Zeitpunkt, da es sich um den ersten Eindruck Ihrer App handelt. Sie erwarten sofortiges und kontinuierliches Feedback vom System und den Apps. Das System und die App wirken fehlerhaft oder schlecht gestaltet, wenn Apps nicht schnell starten. Schlimmer noch, wenn eine App zu lange braucht, um aktiviert zu werden, kann der Process Lifetime Manager (PLM) sie beenden, oder der Benutzer kann sie deinstallieren.
Einführung in die Phasen eines Startups
Der Start eines Projekts umfasst viele bewegliche Teile, und alle müssen ordnungsgemäß koordiniert werden, um die beste Benutzererfahrung zu erzielen. Die folgenden Schritte treten zwischen dem Benutzer, der auf die App-Kachel klickt, und dem angezeigten Anwendungsinhalt auf.
- Die Windows-Shell startet den Prozess, und Main wird aufgerufen.
- Das Application-Objekt wird erstellt.
- (Projektvorlage) Der Konstruktor ruft InitializeComponent auf, wodurch App.xaml analysiert und Objekte erstellt werden.
- Das Ereignis Application.OnLaunched wird ausgelöst.
- (ProjectTemplate) App-Code erstellt einen Frame und navigiert zu "MainPage".
- (ProjectTemplate) Der Mainpage-Konstruktor ruft InitializeComponent auf, wodurch MainPage.xaml analysiert und Objekte erstellt werden.
- ProjectTemplate) Window.Current.Activate() wird aufgerufen.
- Die XAML-Plattform führt den Layoutdurchlauf einschließlich des Messens und Anordnens aus.
- ApplyTemplate bewirkt, dass Steuerelementvorlageninhalte für jedes Steuerelement erstellt werden, was in der Regel der Großteil der Layoutzeit für den Start ist.
- Das Rendern wird aufgerufen, um alle Fensterinhalte zu visualisieren.
- Frame wird dem Desktop Window Manager (DWM) präsentiert.
Weniger auf Ihrem Startup-Weg
Lassen Sie Den Startcodepfad frei von allen Elementen, die für Ihren ersten Frame nicht benötigt werden.
- Wenn Sie Benutzer-DLLs mit Steuerelementen haben, die während des ersten Frames nicht benötigt werden, sollten Sie das Laden verzögern.
- Wenn Sie einen Teil der Benutzeroberfläche haben, der von Daten aus der Cloud abhängig ist, teilen Sie diese Benutzeroberfläche auf. Rufen Sie zunächst die Benutzeroberfläche auf, die nicht von Clouddaten abhängig ist, und rufen Sie die cloudabhängige Benutzeroberfläche asynchron auf. Sie sollten auch das lokale Zwischenspeichern von Daten in Betracht ziehen, damit die Anwendung offline funktioniert oder nicht durch langsame Netzwerkkonnektivität beeinträchtigt wird.
- Zeigen Sie die Fortschrittsanzeige an, wenn Ihre Benutzeroberfläche auf Daten wartet.
- Seien Sie vorsichtig bei App-Designs, die viele Analysen von Konfigurationsdateien oder ui erfordern, die dynamisch von Code generiert werden.
Elementanzahl reduzieren
Die Startleistung in einer XAML-App korreliert direkt mit der Anzahl der Elemente, die Sie während des Starts erstellen. Je weniger Elemente Sie erstellen, desto weniger Zeit wird Ihre App zum Starten benötigen. Berücksichtigen Sie als groben Richtwert, dass die Erstellung jedes Elements 1 ms dauert.
- Vorlagen, die in Elementsteuerelementen verwendet werden, können die größte Auswirkung haben, da sie mehrfach verwendet werden. Siehe ListView- und GridView-Benutzeroberfläche-Optimierung.
- UserControls und Steuerelement-Vorlagen werden erweitert, daher sollten diese ebenfalls berücksichtigt werden.
- Wenn Sie XAML-Code erstellen, der nicht auf dem Bildschirm angezeigt wird, sollten Sie rechtfertigen, ob diese XAML-Teile während des Starts erstellt werden sollen.
Das Visual Studio Live Visual Tree Fenster zeigt die Anzahl der untergeordneten Elemente für jeden Knoten in der Struktur an.
Verwenden Sie Aufschub. Das Zusammenklappen eines Elements oder das Festlegen der Deckkraft auf 0 verhindert nicht, dass das Element erstellt wird. Mit x:Load oder x:DeferLoadStrategy können Sie das Laden eines Benutzeroberfläche-Elements verzögern und es erst bei Bedarf laden. Dies ist eine gute Möglichkeit, die Verarbeitung der Benutzeroberfläche zu verzögern, die während des Startbildschirms nicht sichtbar ist, sodass Sie sie bei Bedarf oder als Teil einer Reihe verzögerter Vorgänge laden können. Um das Laden auszulösen, müssen Sie nur FindName für das Element aufrufen. Ein Beispiel und weitere Informationen finden Sie unter x:Load-Attribut und x:DeferLoadStrategy-Attribut.
Virtualisierung. Wenn Sie Listen- oder Wiederholungsinhalte auf der Benutzeroberfläche haben, wird dringend empfohlen, die UI-Virtualisierung zu verwenden. Wenn die Listen-UI nicht virtualisiert ist, bezahlen Sie die Kosten für das Erstellen aller Elemente im Vorfeld, und dies kann den Start verlangsamen. Siehe ListView- und GridView-Benutzeroberfläche-Optimierung.
Die Anwendungsleistung geht nicht nur um rohe Leistung, es geht auch um die Wahrnehmung. Wenn Sie die Reihenfolge der Vorgänge so ändern, dass visuelle Aspekte zuerst auftreten, wird der Benutzer häufig das Gefühl haben, dass die Anwendung schneller ist. Benutzer betrachten die Anwendung als geladen, wenn sich der Inhalt auf dem Bildschirm befindet. Häufig müssen Anwendungen im Rahmen des Startvorgangs mehrere Aktionen ausführen, von denen nicht alle erforderlich sind, um die Benutzeroberfläche anzuzeigen. Daher sollten diese Elemente verzögert oder mit niedrigerer Priorität als die Benutzeroberfläche behandelt werden.
In diesem Thema geht es um den "ersten Frame", der aus Animation/TV stammt, und es misst, wie lange es dauert, bis Inhalte vom Endbenutzer gesehen werden.
Verbesserung der Wahrnehmung von Startup-Unternehmen
Lassen Sie uns das Beispiel eines einfachen Onlinespiels verwenden, um jede Startphase und verschiedene Techniken zu identifizieren, um dem Benutzer während des gesamten Prozesses Feedback zu geben. In diesem Beispiel ist die erste Aktivierungsphase die Zeit zwischen dem Tippen auf die Kachel des Spiels und dem Beginn der Code-Ausführung durch das Spiel. Während dieser Zeit hat das System keine Inhalte, die dem Benutzer angezeigt werden können, um darauf hinzuweisen, dass das richtige Spiel gestartet ist. Wenn Sie jedoch einen Begrüßungsbildschirm bereitstellen, übergibt dies den Inhalt an das System. Das Spiel informiert den Benutzer dann darüber, dass die erste Aktivierungsphase abgeschlossen wurde, indem er den statischen Begrüßungsbildschirm durch eine eigene Benutzeroberfläche ersetzt, wenn er mit dem Ausführen von Code beginnt.
Die zweite Aktivierungsphase umfasst das Erstellen und Initialisieren von Strukturen, die für das Spiel kritisch sind. Wenn eine App ihre anfängliche Benutzeroberfläche schnell mit den Daten erstellen kann, die nach der ersten Aktivierungsphase verfügbar sind, ist die zweite Phase trivial, und Sie können die Benutzeroberfläche sofort anzeigen. Andernfalls wird empfohlen, dass die App während der Initialisierung eine Ladeseite anzeigt.
Wie die Ladeseite aussieht, liegt bei Ihnen und kann so einfach sein wie das Anzeigen eines Fortschrittsbalkens oder eines Fortschrittskreises. Der wichtigste Punkt ist, dass die App angibt, dass sie Aufgaben ausführt, bevor sie reaktionsfähig werden. Im Falle des Spiels möchte er seinen Anfangsbildschirm anzeigen, aber für diese Benutzeroberfläche müssen einige Bilder und Sounds vom Datenträger in den Arbeitsspeicher geladen werden. Diese Aufgaben dauern ein paar Sekunden, sodass die App den Benutzer informiert, indem der Startbildschirm durch eine Ladeseite ersetzt wird, die eine einfache, zum Thema des Spiels passende Animation zeigt.
Die dritte Phase beginnt, nachdem das Spiel über einen minimalen Satz von Informationen verfügt, um eine interaktive Benutzeroberfläche zu erstellen, die die Ladeseite ersetzt. Zu diesem Zeitpunkt sind die einzigen Informationen, die für das Onlinespiel verfügbar sind, der Inhalt, den die App von der Festplatte geladen hat. Das Spiel kann mit genügend Inhalt ausgeliefert werden, um eine interaktive Benutzeroberfläche zu erstellen. aber da es sich um ein Onlinespiel handelt, ist es erst funktionsfähig, wenn es eine Verbindung mit dem Internet herstellt und einige zusätzliche Informationen herunterlädt. Bis alle Benötigten Informationen funktionsfähig sind, kann der Benutzer mit der Benutzeroberfläche interagieren, aber Features, die zusätzliche Daten aus dem Web benötigen, sollten Feedback geben, dass inhalte noch geladen werden. Es kann einige Zeit dauern, bis eine App voll funktionsfähig ist, daher ist es wichtig, dass die Funktionalität so schnell wie möglich verfügbar gemacht wird.
Nachdem wir nun die drei Aktivierungsstufen im Onlinespiel identifiziert haben, binden wir sie an den tatsächlichen Code.
Phase 1
Bevor eine App gestartet wird, muss sie dem System mitteilen, was als Begrüßungsbildschirm angezeigt werden soll. Dies geschieht, indem ein Bild und eine Hintergrundfarbe für das SplashScreen-Element im Manifest einer App bereitgestellt werden, wie im Beispiel gezeigt. Windows zeigt dies an, nachdem die App mit der Aktivierung begonnen hat.
<Package ...>
...
<Applications>
<Application ...>
<VisualElements ...>
...
<SplashScreen Image="Images\splashscreen.png" BackgroundColor="#000000" />
...
</VisualElements>
</Application>
</Applications>
</Package>
Weitere Informationen finden Sie unter Hinzufügen eines Begrüßungsbildschirms.
Verwenden Sie den Konstruktor der App nur, um Datenstrukturen zu initialisieren, die für die App von entscheidender Bedeutung sind. Der Konstruktor wird nur aufgerufen, wenn die App zum ersten Mal ausgeführt wird, und nicht unbedingt jedes Mal, wenn die App aktiviert wird. Beispielsweise wird der Konstruktor nicht für eine App aufgerufen, die ausgeführt, im Hintergrund platziert und dann über den Suchvertrag aktiviert wird.
Phase 2
Es gibt eine Reihe von Gründen, aus denen eine App aktiviert werden kann, von denen jeder anders behandelt werden soll. Sie können OnActivated, OnCachedFileUpdaterActivated, OnFileActivated, OnFileOpenPickerActivated, OnFileSavePickerActivated, OnLaunched, OnSearchActivatedund OnShareTargetActivated Methoden überschreiben, um die einzelnen Aktivierungsgründe zu behandeln. Eine der Aktionen, die eine App in diesen Methoden ausführen muss, ist, eine Benutzeroberfläche zu erstellen, sie Window.Contentzuzuweisen, und dann Window.Activateaufzurufen. An diesem Punkt wird der Begrüßungsbildschirm durch die Benutzeroberfläche ersetzt, die die App erstellt hat. Dieses visuelle Element könnte entweder ein Ladebildschirm oder die tatsächliche Benutzeroberfläche der App sein, wenn genügend Informationen bei der Aktivierung verfügbar sind, um diese zu erstellen.
public partial class App : Application
{
// A handler for regular activation.
async protected override void OnLaunched(LaunchActivatedEventArgs args)
{
base.OnLaunched(args);
// Asynchronously restore state based on generic launch.
// Create the ExtendedSplash screen which serves as a loading page while the
// reader downloads the section information.
ExtendedSplash eSplash = new ExtendedSplash();
// Set the content of the window to the extended splash screen.
Window.Current.Content = eSplash;
// Notify the Window that the process of activation is completed
Window.Current.Activate();
}
// a different handler for activation via the search contract
async protected override void OnSearchActivated(SearchActivatedEventArgs args)
{
base.OnSearchActivated(args);
// Do an asynchronous restore based on Search activation
// the rest of the code is the same as the OnLaunched method
}
}
partial class ExtendedSplash : Page
{
// This is the UIELement that's the game's home page.
private GameHomePage homePage;
public ExtendedSplash()
{
InitializeComponent();
homePage = new GameHomePage();
}
// Shown for demonstration purposes only.
// This is typically autogenerated by Visual Studio.
private void InitializeComponent()
{
}
}
Partial Public Class App
Inherits Application
' A handler for regular activation.
Protected Overrides Async Sub OnLaunched(ByVal args As LaunchActivatedEventArgs)
MyBase.OnLaunched(args)
' Asynchronously restore state based on generic launch.
' Create the ExtendedSplash screen which serves as a loading page while the
' reader downloads the section information.
Dim eSplash As New ExtendedSplash()
' Set the content of the window to the extended splash screen.
Window.Current.Content = eSplash
' Notify the Window that the process of activation is completed
Window.Current.Activate()
End Sub
' a different handler for activation via the search contract
Protected Overrides Async Sub OnSearchActivated(ByVal args As SearchActivatedEventArgs)
MyBase.OnSearchActivated(args)
' Do an asynchronous restore based on Search activation
' the rest of the code is the same as the OnLaunched method
End Sub
End Class
Partial Friend Class ExtendedSplash
Inherits Page
Public Sub New()
InitializeComponent()
' Downloading the data necessary for
' initial UI on a background thread.
Task.Run(Sub() DownloadData())
End Sub
Private Sub DownloadData()
' Download data to populate the initial UI.
' Create the first page.
Dim firstPage As New MainPage()
' Add the data just downloaded to the first page
' Replace the loading page, which is currently
' set as the window's content, with the initial UI for the app
Window.Current.Content = firstPage
End Sub
' Shown for demonstration purposes only.
' This is typically autogenerated by Visual Studio.
Private Sub InitializeComponent()
End Sub
End Class
Apps, die im Aktivierungshandler eine Ladeseite anzeigen, beginnen im Hintergrund mit der Erstellung der Benutzeroberfläche. Nachdem dieses Element erstellt wurde, tritt das FrameworkElement.Loaded-Ereignis auf. Im Ereignishandler ersetzen Sie den Inhalt des Fensters, der derzeit der Ladebildschirm ist, durch die neu erstellte Startseite.
Es ist wichtig, dass eine App mit einem erweiterten Initialisierungszeitraum eine Ladeseite anzeigt. Abgesehen von der Bereitstellung des Benutzerfeedbacks zum Aktivierungsprozess wird der Prozess beendet, wenn Window.Activate nicht innerhalb von 15 Sekunden nach dem Start des Aktivierungsprozesses aufgerufen wird.
partial class GameHomePage : Page
{
public GameHomePage()
{
InitializeComponent();
// add a handler to be called when the home page has been loaded
this.Loaded += ReaderHomePageLoaded;
// load the minimal amount of image and sound data from disk necessary to create the home page.
}
void ReaderHomePageLoaded(object sender, RoutedEventArgs e)
{
// set the content of the window to the home page now that it's ready to be displayed.
Window.Current.Content = this;
}
// Shown for demonstration purposes only.
// This is typically autogenerated by Visual Studio.
private void InitializeComponent()
{
}
}
Partial Friend Class GameHomePage
Inherits Page
Public Sub New()
InitializeComponent()
' add a handler to be called when the home page has been loaded
AddHandler Me.Loaded, AddressOf ReaderHomePageLoaded
' load the minimal amount of image and sound data from disk necessary to create the home page.
End Sub
Private Sub ReaderHomePageLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
' set the content of the window to the home page now that it's ready to be displayed.
Window.Current.Content = Me
End Sub
' Shown for demonstration purposes only.
' This is typically autogenerated by Visual Studio.
Private Sub InitializeComponent()
End Sub
End Class
Ein Beispiel für die Verwendung erweiterter Begrüßungsbildschirme finden Sie im Beispiel Begrüßungsbildschirm.
Phase 3
Nur weil die App die Benutzeroberfläche angezeigt hat, bedeutet dies nicht, dass sie vollständig einsatzbereit ist. Im Falle unseres Spiels wird die Benutzeroberfläche mit Platzhaltern für Features angezeigt, die Daten aus dem Internet erfordern. An diesem Punkt lädt das Spiel die zusätzlichen Daten herunter, die erforderlich sind, um die App voll funktionsfähig zu machen, und Funktionen werden schrittweise freigeschaltet, sobald Daten abgerufen werden.
Manchmal kann ein Großteil der für die Aktivierung benötigten Inhalte mit der App verpackt werden. Dies ist der Fall bei einem einfachen Spiel. Dies macht den Aktivierungsprozess recht einfach. Aber viele Programme (z. B. Nachrichtenleser und Fotoanzeigen) müssen Informationen aus dem Web abrufen, um funktionsfähig zu werden. Diese Daten können groß sein und eine gewisse Zeit in Anspruch nehmen, um sie herunterzuladen. Wie die App diese Daten während des Aktivierungsprozesses abruft, kann einen erheblichen Einfluss auf die wahrgenommene Leistung der App haben.
Sie könnten minutenlang einen Ladebildschirm oder, schlimmer noch, einen Startbildschirm anzeigen, wenn eine App versucht, einen gesamten Datensatz herunterzuladen, der für die Funktionalität in Phase eins oder zwei der Aktivierung benötigt wird. Dadurch sieht eine App so aus, als ob sie nicht mehr reagiert oder vom System beendet wird. Es wird empfohlen, dass eine App die minimale Datenmenge herunterladet, um eine interaktive Benutzeroberfläche mit Platzhalterelementen in Phase 2 anzuzeigen und dann schrittweise Daten zu laden, die die Platzhalterelemente ersetzen, in Phase 3. Weitere Informationen zum Umgang mit Daten finden Sie unter Optimize ListView and GridView.
Wie genau eine App auf jede Startphase reagiert, liegt ganz bei Ihnen, aber indem Sie dem Benutzer so viel Feedback wie möglich bereitstellen (Begrüßungsbildschirm, Ladebildschirm, Benutzeroberfläche beim Laden von Daten), fühlt sich der Benutzer, als ob die App und das System schnell sind.
Minimieren von verwalteten Assemblys im Startpfad
Wiederverwendbarer Code kommt häufig in Form von Modulen (DLLs), die in einem Projekt enthalten sind. Das Laden dieser Module erfordert den Zugriff auf den Datenträger, und wie Sie sich vorstellen können, können sich die Kosten dafür addieren. Dies hat die größten Auswirkungen auf den Kaltstart, kann sich aber auch auf den warmen Start auswirken. Im Fall von C# und Visual Basic versucht die CLR, diese Kosten so weit wie möglich zu verzögern, indem Assemblys bei Bedarf geladen werden. Das heißt, die CLR lädt ein Modul nicht, bevor eine auszuführende Methode darauf verweist. Verweisen Sie daher nur auf Assemblys, die zum Starten Ihrer App im Startcode erforderlich sind, damit die CLR keine unnötigen Module lädt. Wenn Sie nicht verwendete Codepfade in Ihrem Startpfad mit unnötigen Verweisen haben, können Sie diese Codepfade auf andere Methoden verschieben, um unnötige Ladevorgänge zu vermeiden.
Eine weitere Möglichkeit zur Reduzierung von Modulbelastungen besteht darin, Ihre App-Module zu kombinieren. Das Laden einer großen Assembly dauert in der Regel weniger Zeit als das Laden von zwei kleinen Assemblys. Dies ist nicht immer möglich, und Sie sollten Module nur kombinieren, wenn dies keinen wesentlichen Unterschied bei der Entwicklerproduktivität oder der Wiederverwendbarkeit von Code macht. Sie können Tools wie PerfView oder den Windows Performance Analyzer (WPA) verwenden, um herauszufinden, welche Module beim Start geladen werden.
Erstellen intelligenter Webanforderungen
Sie können die Ladezeit einer App erheblich verbessern, indem Sie deren Inhalte lokal verpacken, einschließlich XAML, Bilder und anderen dateien, die für die App wichtig sind. Datenträgervorgänge sind schneller als Netzwerkvorgänge. Wenn eine App eine bestimmte Datei bei der Initialisierung benötigt, können Sie die gesamte Startzeit reduzieren, indem Sie sie vom Datenträger laden, anstatt sie von einem Remoteserver abzurufen.
Journal- und Cacheseiten effizient verwalten
Das Rahmen-Steuerelement bietet Navigationsfunktionen. Es bietet Navigation zu einer Seite (Navigate-Methode), Navigationsprotokollierung (BackStack/ForwardStack-Eigenschaften, GoForward/GoBack-Methode), Seitenzwischenspeicherung (Page.NavigationCacheMode) und Unterstützung der Serialisierung (GetNavigationState-Methode).
Die Leistung, die Sie mit Frame beachten sollten, liegt in erster Linie im Bereich des Journalings und des Seiten-Caches.
Rahmenprotokollierung. Wenn Sie mit Frame.Navigate() zu einer Seite wechseln, wird der Frame.BackStack-Auflistung ein PageStackEntry für die aktuelle Seite hinzugefügt. PageStackEntry ist relativ klein, aber es gibt keine festgelegte Begrenzung für die Größe der BackStack-Sammlung. Möglicherweise könnte ein Benutzer in einer Schleife navigieren und diese Sammlung unbegrenzt vergrößern.
Der PageStackEntry enthält auch den Parameter, der an die Frame.Navigate()-Methode übergeben wurde. Es wird empfohlen, dass dieser Parameter ein primitiver serialisierbarer Typ (z. B. ein Int oder eine Zeichenfolge) ist, damit die Frame.GetNavigationState()-Methode funktioniert. Dieser Parameter könnte jedoch potenziell auf ein Objekt verweisen, das größere Mengen an Arbeitssatz oder anderen Ressourcen enthält, wodurch jeder Eintrag im BackStack viel teurer wird. So könnten Sie z. B. eine StorageFile als Parameter verwenden, und folglich behält der BackStack eine unbestimmte Anzahl von Dateien offen.
Daher wird empfohlen, die Navigationsparameter klein zu halten und die Größe des BackStack einzuschränken. Der BackStack ist ein Standardvektor (IList in C#, Platform::Vector in C++/CX) und kann daher einfach durch Entfernen von Einträgen gekürzt werden.
Seitenzwischenspeicherung. Wenn Sie mit der Frame.Navigate-Methode zu einer Seite navigieren, wird standardmäßig eine neue Instanz der Seite instanziiert. Ähnlich, wenn Sie dann mit Frame.GoBack zurück zur vorherigen Seite navigieren, wird eine neue Instanz der vorherigen Seite zugewiesen.
Frame bietet jedoch einen optionalen Seitencache, der diese Instanziierungen vermeiden kann. Verwenden Sie die Eigenschaft Page.NavigationCacheMode, um eine Seite im Cache zu speichern. Wenn Sie diesen Modus auf "Erforderlich" festlegen, wird erzwungen, dass die Seite zwischengespeichert wird. Wenn Sie ihn auf "Aktiviert" festlegen, kann sie zwischengespeichert werden. Standardmäßig beträgt die Cachegröße 10 Seiten, dies kann jedoch mit der Frame.CacheSize-Eigenschaft überschrieben werden. Alle erforderlichen Seiten werden zwischengespeichert, und wenn es weniger als die vorgesehene Anzahl erforderlicher Seiten im Cache gibt, können auch aktivierte Seiten zwischengespeichert werden.
Das Zwischenspeichern von Seiten kann die Leistung verbessern, indem Instanziierungen vermieden und somit die Navigationsleistung verbessert wird. Das Zwischenspeichern von Seiten kann die Leistung beeinträchtigen, indem durch übermäßiges Zwischenspeichern der Arbeitssatz negativ beeinflusst wird.
Daher wird empfohlen, die Seitenzwischenspeicherung entsprechend Ihrer Anwendung zu nutzen. Angenommen, Sie haben eine App, die eine Liste von Elementen in einem Frame anzeigt, und wenn Sie auf ein Element tippen, navigiert er den Frame zu einer Detailseite für dieses Element. Die Listenseite soll vermutlich im Cache gespeichert werden. Wenn die Detailseite für alle Elemente identisch ist, sollte sie wahrscheinlich auch zwischengespeichert werden. Wenn die Detailseite jedoch vielfältiger ist, ist es möglicherweise besser, den Cache ausgeschaltet zu lassen.