Bisher haben meine Tests gezeigt, dass alle Standardansätze, Beispiele und Frameworks, die das MVVM-Muster in Silverlight nutzen, unter einem riesigen Problem leiden: massive Speicherlecks, die VMs davon abhalten, Müll zu sammeln.
Offensichtlich ist das ein riesiger und lächerlicher Anspruch - also erwarte ich, dass jemand eine offensichtliche Antwort darauf hat, warum und wo ich falsch liege:)
Die zu reproduzierenden Schritte sind einfach:
<TextBox Text="{Binding SomeText}" />
Dies erstellt eine Referenzkette, die sich von der Wurzel bis zu einer BindingExpression zu Ihrem Ansichtsmodell erstreckt. Sie können dann die Ansicht aus Ihrer UI-Struktur sowie alle Verweise auf die VM entfernen. Die VM wird jedoch dank der Stamm- & lt; & gt; & gt; BindingExpression & lt; & gt; & gt; VM-Referenzkette nie in den Garbage Collection-Prozess aufgenommen.
Ich habe zwei Beispiele zur Veranschaulichung des Problems erstellt. Sie verfügen über eine Schaltfläche zum Erstellen eines neuen View / View-Modells (das alle Verweise auf die alten Images ablegen soll) und eine Schaltfläche, die die Garbage-Collection und Berichte zur aktuellen Speicherbelegung erzwingt.
Beispiel 1 ist ein super-abgespecktes Kalibrierungsmikro-Beispiel. Beispiel 2 verwendet keine Frameworks und veranschaulicht das Problem auf die einfachste Weise, die mir einfällt.
Für diejenigen, die vielleicht helfen möchten, aber die Beispielprojekte nicht herunterladen möchten, hier ist der Code für Beispiel 2. Wir beginnen mit einem Viewmodel namens FooViewModel:
%Vor%Es stellt einfach eine String-Eigenschaft namens FooText zur Verfügung, die wir ebenfalls binden werden. INotifyPropertyChanged ist notwendig, um das Binden zu erleichtern.
Dann haben wir eine Ansicht namens FooView, die ein usercontrol ist mit:
%Vor%(Namespaces wurden aus Platzgründen weggelassen)
Das wichtige Bit hier ist das Textfeld, das an die FooText-Eigenschaft gebunden ist. Natürlich müssen wir den Datenkontext, den ich gewählt habe, im Codebehind setzen, anstatt einen ViewModelLocator einzuführen:
%Vor%MainPage sieht so aus:
%Vor%mit dem folgenden im folgenden Code:
%Vor%Hinweis: Um das Problem zu replizieren, vergewissern Sie sich, dass Sie etwas in das Textfeld eingeben, da ich glaube, dass der Bindungsausdruck erst erstellt wird, wenn er benötigt wird.
Es ist erwähnenswert, dass dieser KB-Artikel verwandt sein kann, ich bin jedoch nicht überzeugt, seit ' Methode 2 'Workaround scheint keine Wirkung zu haben, und die Referenzkette scheint nicht übereinzustimmen.
Ich bin mir auch nicht sicher, ob das wichtig ist, aber ich habe CLR Profiler um die Ursache zu diagnostizieren.
Aktualisierung:
Wenn jemand testen möchte, und ihre Ergebnisse in einem Kommentar melden, hosting ich die Silverlight-Anwendung über Dropbox hier: Hosted Beispiel . Um zu reproduzieren: Drücken Sie die obere Taste, tippen Sie etwas, drücken Sie die obere Taste, tippen Sie etwas, drücken Sie die obere Taste. Dann drücke den Knopf. Wenn 10 MB (oder eine andere Menge, die nicht zunimmt) gemeldet wird, tritt kein Speicherverlust auf.
Bisher scheint das Problem auf ALLEN unseren Entwicklungsmaschinen zu passieren, die ThinkPad w510 (43192RU) mit 12 GB Ram, 64 Bit Win 7 Enterprise sind. Dies schließt einige ein, auf denen keine Entwicklungstools installiert waren. Es kann erwähnenswert sein, dass sie VMWare Workstation ausführen.
Das Problem scheint NICHT auf anderen Rechnern zu liegen, die ich ausprobiert habe - einschließlich einiger Heim-PCs und anderer PCs im Büro. Wir haben einige SL-Versionen, Speicherkapazität und wahrscheinlich VMware ausgeschlossen. Habe noch immer keine Ursache gefunden.
Eine Lösung muss noch gefunden werden , aber das Problem ist jetzt identifiziert. Dieses Verhalten tritt auf, wenn die Automatisierungsfunktionen von Silverlights aufgrund folgender Ursachen aufgerufen werden:
Weitere Informationen finden Sie hier: Ссылка
So ein neues Problem Oberflächen: Wie deaktivieren wir automationpeers oder auf andere Weise zu reinigen sie richtig?
Dieser Beitrag zeigt einen Ansatz: WPF UserControl Speicherleck
Es ist jedoch keine wirklich brauchbare Lösung, da wir jede Silverlight-Kontrolle, die wir verwenden möchten, außer Kraft setzen müssen, ganz zu schweigen von den Kontrollschablonen komplexer Kontrollen.
Ich werde meine Antwort ändern, wenn jemand eine gute Lösung finden kann, aber im Moment scheint es keine zu geben ...
Bearbeiten:
Hier ist eine nette kleine Problemumgehung, die den Job zu erledigen scheint. Fügen Sie einfach den folgenden Parameter in Ihr HTML ein, in dem Sie das silverlight-Objekt definieren:
%Vor%Ein Nebeneffekt der Ausführung im "fensterlosen" Modus ist, dass die Automatisierung nicht funktioniert:)
In Ihrem zweiten Beispiel ist kein Speicherleck vorhanden.
Nachdem Sie eine neue FooView
-Instanz auf Ihre ContentControl
mit myContent.Content = new FooView();
angewendet haben, gibt es keine weitere Referenz für das gesamte View + ViewModel-Objektdiagramm.
Bei Bedarf wird es Müll gesammelt.
Vielleicht sollten Sie klären, was Sie denken lassen, dass es ein Speicherleck gibt (d. h. Statistiken, Repro-Schritte ... etc.)
Tags und Links memory-leaks c# silverlight mvvm caliburn.micro