Frage

Update : Ich habe versucht, diese auf einem anderen, sauber installiert, Maschine. Das konnte ich auf dieser Maschine nicht reproduzieren. Wenn ich herausfinden, was zu beleidigen (VSStudio) Komponente bewirkt dies, werde ich Sie wissen lassen.

Ich schaffe einige UIElements von Code hinter und rechnete die Garbage Collection Sachen zu klären. Allerdings sind die Objekte nicht frei ed zu der Zeit ich es erwartet hatte. Ich erwarte sie freeed bei RemoveAt (0) werden, aber sie werden erst am Ende des Programms befreit.

Wie kann ich die Objekte mache befreit werden, wenn sie von den Kindern Sammlung der Leinwand entfernt?

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
    MouseDown="Window_MouseDown">
  <Grid>
    <Canvas x:Name="main" />
  </Grid>
</Window>

Der Code hinter lautet:

public partial class MainWindow : Window
{
  public MainWindow()
  {
    InitializeComponent();
  }

private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
  GC.Collect(); // This should pick up the control removed at a previous MouseDown
  GC.WaitForPendingFinalizers(); // Doesn't help either

  if (main.Children.Count == 0)
    main.Children.Add(new MyControl() { Background = Brushes.Yellow, Width = 100, Height = 50 });
  else
    main.Children.RemoveAt(0);
 }
}

public class MyControl : UserControl
{
  ~MyControl()
  {
    Debug.WriteLine("Goodbye");
  }
}

Keine korrekte Lösung

Andere Tipps

Ändern

public class MyControl : UserControl

public class MyControl : ContentControl

, und es wird zum Abschied (nach dem zweiten Mal, wenn Sie die Steuerung entfernen.) Sagt, dass ich überprüfte auch der Speicher nicht durch die Verwendung

entweicht

Debug.WriteLine("mem: " + GC.GetTotalMemory(true).ToString());

Auch finden Sie unter diese :

  

Sie haben die Testcontrol entfernen, indem grid.Children löschen, aber es ist nicht sofort, die für die Garbage Collection. Mehrere asynchronen Operationen auf ihnen anstehen, und es kann nicht GC'd abgeschlossen, bis diese Operationen sein (dazu gehören auch das Unloaded Ereignis und einigen Bereinigungscode in der Rendering-Engine erhöht).

     

ich festgestellt, dass, wenn Sie, bis diese Vorgänge abgeschlossen warten (etwa durch einen Dispatcher Betrieb Planung bei ContextIdle Priorität) wird die Testcontrol, die für GC, unabhängig von der Anwesenheit einer Bindung an dem Textblock.

Usercontrol muss entweder ein internes Ereignis haben, die nicht schnell aufzuräumen, oder es könnte ein Fehler mit VS2010 RC sein. Ich würde dies durch connect berichten, aber jetzt wechseln zu Content.

Da Sie Usercontrol verwenden, gehe ich davon aus Sie auch Schalter haben, werde die generic.xaml Vorlage zu verwenden. Das ist nicht allzu schwierig, eine Umstellung (und für die meisten Dinge ist eine bessere Lösung.)

Objekte in C # werden nicht automatisch „befreit“, sobald sie nicht mehr verwendet werden.

Rather, wenn Sie das Objekt aus Ihrem Control entfernen, wird es , die für die Garbage Collection an diesem Punkt, vorausgesetzt, Sie haben keine anderen Verweise auf das UIElement.

Sobald ein Objekt ist „unbewurzelten“ (es gibt keine Hinweise, die direkt oder indirekt von jedem einzelnen Objekt in Ihrer Anwendung), wird es für die Sammlung in Betracht. Der Garbage Collector wird dann schließlich aufzuräumen Ihre Aufgabe, aber wenn dies geschieht, ist nicht etwas, das man (in der Regel) Kontrolle.

Just Vertrauen, dass es schließlich aufgeräumt wird erhalten. Das ist die Schönheit von C # (.NET und im Allgemeinen.) - das Management und Sorge, dies für Dich gehandhabt wird


Edit: Nach einigen Tests, scheint es, dass das Fenster enthält einen Verweis auf das UIElement bis zum nächsten Layout weiter. Sie können dies einen Aufruf auftreten erzwingen, indem Sie fügte hinzu:

this.UpdateLayout();

Nach dem Element (e) aus der Leinwand Kinder zu entfernen. Dies bewirkt, dass die Objekte für GC zur Verfügung stehen.

Es gibt drei Generationen von Garbage Collection in C #, so dass selbst wenn es keine Hinweise auf Ihre Objekte sind es 3 Garbage Collection nehmen könnten, sie zu befreien.

Sie können die GC.Collect verwenden () 's-Parameter eine dritte Generation der Garbage Collection zu erzwingen,
aber die beste approuch ist nicht GC.Collect () selbst zu nennen,
verwenden Sie stattdessen die IDisposable-Schnittstelle und binden die Kinder zu einem ObservableCollection und wenn Sie erhalten ein Collection Ereignis Dispose () von irgendwelchen entfernten Objekten.

Sie können dies von Interesse finden. Ich fand heraus, vor kurzem, dass x: Name-Markup-Erweiterung speichert ein Verweis auf das UIElement in der übergeordneten Steuerung in einem durch den String Namen eingegeben Wörterbuch.

Wenn Sie die UIElement von seinem übergeordneten entfernen, hält das Wörterbuch einen Verweis auf das Steuerelement.

  

Es gibt eine Blog-Post / Video-Debuggen das Speicherleck hier: WPF   x: Name-Speicherverlust

Die Lösung ist nicht x zu verwenden: Name oder dass die Kontrollen, um sicherzustellen, dass von x am Leben gehalten werden. Namen werden gelöscht aus, um nicht zu viel Speicher zu verbrauchen, bevor ein Abschnitt des visuellen Struktur gesammelt

Update: Sie deregistrieren eine benannte Klasse mit der Namescope

this.grid.Children.Remove(child); // Remove the child from visual tree
NameScope.GetNameScope(this).UnregisterName("child"); // remove the keyed name
this.child = null; // null the field

// Finally it is free to be collected! 

Wir hatten das gleiche Problem und dachte auch, dass dies der Grund sein kann. Aber wir analysiert unser Projekt mit Tools Memory Profiler und gefunden, dass es nichts mit dem Grid.Remove oder Grid.RemoveAt zu tun. Deshalb denke ich, mein Vorschlag nur einen Blick Ihr Projekt auf dem Speicher-Profiler-Tool hat und sehen, was in Ihrem Projekt passiert. hofft, dass dies hilft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top