2014-08-27 13 views
5

Ich habe eine kleine Schwierigkeit beim Anzeigen des Fortschritts von Assemblys, die in die AppDomain.CurrentDomain geladen werden.Wie kann ich den Fortschritt beim Laden von Assemblys in die aktuelle Anwendungsdomäne in .Net auf einem Startbildschirm melden?

Ich möchte einen Begrüßungsbildschirm mit einer Fortschrittsleiste anzeigen. Ich möchte diese Fortschrittsleiste aktualisieren können, wenn jede Assembly in den Speicher der AppDomain geladen wird. Auf diese Weise erhalten Benutzer einen visuellen Hinweis auf den Fortschritt des Anwendungsstarts.

Es ist mir egal, dass Assemblys geladen werden, bevor der Startbildschirm gerendert wird, der eigentlich nur ein Standard-WPF-Fenster mit einer Fortschrittsleiste ist. Sobald ein Begrüßungsbildschirm geladen ist, möchte ich die Assemblies beim Laden melden. Ich lade diese Baugruppen nicht manuell.

Bisher habe ich das Startup-Ereignis in App.xaml mit folgendem Markup behandelt:

Startup="Application_Startup" 

Der entsprechende Code-behind für die Inbetriebnahme ist wie folgt:

private void Application_Startup(object sender, StartupEventArgs e) 
{ 
SplashScreen.Show<SplashScreen>(); 
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; 
} 

void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args) 
{ 
    SplashScreen.CallSplashScreenMethod<SplashScreen>(x => x.Text(args.LoadedAssembly.GetName().Name)); 
} 

Dies funktioniert wie ich erwarte, Es wird ein Begrüßungsbildschirm angezeigt und alle Baugruppen, die zum Zeitpunkt der Anzeige des Begrüßungsbildschirms geladen werden, werden problemlos auf dem Bildschirm angezeigt.

splashscreen

Das Problem hier ist, dass ich nicht eine Art und Weise der Berichterstattung Fortschritte von Baugruppen wird geladen sehen.

Baugruppen scheinen nicht linear in einer bestimmten Reihenfolge geladen zu sein. Aus diesem Grund bin ich nicht sicher, wie die Anzahl der verbleibenden Baugruppen berechnet werden soll. Ich kann keinen offensichtlichen Weg zu sehen, welche Baugruppen gerade geladen werden.

Wenn ich könnte eine Liste von Baugruppen erhalten noch von der CLR geladen werden ich entweder durch Verwendung einer Standardzahl, entlang der Linien

progress = numberOfLoadedAssemblies/totalNumberOfAssemblies * 100; 

Oder durch die Implementierung der Logik von Chris Marisic's excellent answer on using a weighted average einen Fortschrittsbalken implementieren könnte

Ich kann keine triviale "Directory.GetFiles(). Länge" Um die Gesamtzahl der Baugruppen geladen werden. Der Grund dafür ist, dass die CLR Baugruppen nicht in einer bestimmten Reihenfolge lädt. Es scheint einige Assemblys aus dem Anwendungsstamm zu laden, dann einige aus dem GAC, dann mehr aus dem Anwendungsstamm.

Was ich gerne wissen würde, ist, wenn es eine Möglichkeit gibt, eine Liste von verbleibenden Baugruppen geladen werden.

+2

Dies würde davon ausgehen, dass Sie genau wissen, wie lange es dauern wird. Natürlich nicht. Man könnte höchstens Assemblys zählen, das ist aber sehr unwahrscheinlich repräsentativ, da das Laden von Baugruppen blind ist. Es ist Jitting und Code in den Assemblys auszuführen, der Zeit braucht. Behalte, was du hast. –

+0

Können Sie einfach die Anzahl der Aufrufe von CurrentDomain_AssemblyLoad zählen und den Fortschrittsbalken darauf basierend aktualisieren? – Trisped

+0

@Trisped Es besteht eine gute Chance, dass sich die Anzahl der Assemblies ändert, wenn ich meinem Projekt zusätzliche Funktionen hinzufüge. Danke für deine und Hans Kommentare bis jetzt. –

Antwort

3

Wie andere gesagt haben, können Sie nicht einfach davon ausgehen, dass 9 Baugruppen von 10 geladen 90% bedeuten. Sie können diese Annahmen jedoch viel realistischer machen.

Scannen Sie die Dateiinformationen aller Assemblys, die geladen werden, damit Sie die Dateigröße jeder Assembly haben. Erstellen Sie nun einen gewichteten Wert für die "durchschnittliche" Baugruppe.

var totalSize = assemblies.Select(x=> x.FileSize).Sum(); 
var averageSize = totalSize/assemblies.Count(); 

var averageChange = averageSize/totalSize; 

Ihre Fortschrittsbalken Unter der Annahme ist eine Skala von 0 bis 1 ist, könnten Sie einfach averageChange hinzufügen jedes Mal eine andere Assembly geladen wird.

Oder Sie könnten tatsächlich die geladenen Bytes gegen die Gesamtgröße für den Fortschrittsbalken zählen. Ich würde persönlich mit meiner Durchschnittsmethode gehen, um zu verhindern, dass der Fortschrittsbalken von [-] zu [-------------------] von einer einzelnen Baugruppe geht. Benutzer sind nicht an nichtlineare Änderungen gewöhnt und neigen nicht dazu, nichtlinearen Änderungen zu vertrauen. Wenn man ihnen einen linear zunehmenden Fortschrittsbalken gibt, der fast genau nach dem Laden endet, gibt man den Menschen das Gefühl, dass die Dinge funktionieren und bald erledigt sein werden. Erratische Sprünge in Fortschrittsbalken machen die Benutzer fühlenSystem ist erratisch und nicht vertrauenswürdig.

Eine Sache, die ich nicht untertreiben kann ist, wie einfach es ist, Ihre Benutzer mit einem Fortschrittsbalken zu verärgern. Nichts verärgert Benutzer mehr als eine Fortschrittsleiste, die Treffer schnell zu 99% füllt und stoppt. Sie fühlen sich wie das Programm eingefroren. Sie brauchen auch eine visuelle Anzeige, dass zwischen jeder Zähler, dass die Dinge nicht eingefroren sind. Sie wollen auch nicht für eine lange Zeit rumsitzen (das sind wenige Sekunden) und sehen, wie sich ein Fortschrittsbalken füllt und dann auf Null zurückfaltet.

+1

Ich mag diese Antwort, ich habe es upvoted, wie es eine nette Idee ist und hebt einen ziemlich guten Punkt in Bezug auf Laden Bars im Allgemeinen. Danke, dass du dir die Zeit genommen hast, dies für mich zu schreiben! Es ist nicht ganz das, wonach ich suche. Das Problem ist, dass ich keine Dateiinformationen für Assemblys durchsuchen kann, die im GAC (Global Assembly Cache) enthalten sind. Ich muss wissen, wie man alle Assemblys zählt, die geladen werden müssen, die Dateien befinden sich nicht notwendigerweise alle im selben Verzeichnis, was bedeutet, dass ich nicht einfach ein triviales "Dateiinfo im Verzeichnis 'x'" machen kann. Assemblies scheinen auch nicht in einer bestimmten Reihenfolge geladen zu sein. –

+0

'Die Dateien befinden sich nicht unbedingt alle im selben Verzeichnis' Sie sollten über genügend Informationen verfügen, um alle Standorte durchsuchen zu können. Ich würde mich nicht mit dem GAC anlegen und nur den durchschnittlichen Änderungswert skalieren, der alles gut funktioniert.Du wirst das nicht perfekt machen, du brauchst nur die beste Anstrengung. –