Pregunta

Actualizar : He intentado esto en otro, de forma más limpia con aparato, máquina. No podía reproducir este en esa máquina. Si me entero de lo que ofender (VSStudio) componente provoca esto, voy a saber.

puedo crear algunos UiElements de código detrás y estaba anticipando la recolección de basura para aclarar las cosas. Sin embargo, los objetos no son libres-ed en el momento que yo esperaba. Yo estaba esperando que sean freeed en RemoveAt (0), pero sólo se liberan al final del programa.

¿Cómo puedo hacer que los objetos sean liberados cuando se retira de la colección de los niños lienzo?

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

El detrás de código es:

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");
  }
}

No hay solución correcta

Otros consejos

Cambiar

public class MyControl : UserControl

a

public class MyControl : ContentControl

y va a decir adiós (después de la segunda vez que se quita el control.) También verifiqué la memoria no se escape utilizando

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

Además, vea este :

  

quitar el TestControl en la limpieza de grid.Children, pero no es inmediatamente elegibles para la recolección de basura. Varias operaciones asincrónicas en él están pendientes, y no pueden ser GC'd hasta que esas operaciones completas (que incluyen elevar el evento descargado y algún código de limpieza en el motor de renderizado).

     

I verificado que si usted espera hasta que estas operaciones completas (digamos mediante la programación de una operación de Dispatcher con la prioridad ContextIdle), el TestControl se convierte en elegible para GC, independientemente de la presencia de un enlace en el TextBlock.

control de usuario debe tener ya sea un evento interno que no limpiar de forma rápida, o podría ser un error con VS2010 RC. Me informo de esto a través de conexión, pero por ahora cambio a ContentControl.

Dado que está utilizando control de usuario, supongo que también tendrá que cambiar a utilizar la plantilla Generic.xaml. Eso no es demasiado difícil de conmutación (y para la mayoría de las cosas es una solución mejor.)

Objetos en C # no son automáticamente "liberado" tan pronto como ya no se utilizan.

Por el contrario, cuando se quita el objeto de su control, se convierte en aptos para reciclaje en ese punto, suponiendo que tiene ninguna otra referencia a la UIElement.

Una vez que un objeto es "sin raíces" (no hay referencias, directa o indirectamente, de cualquier objeto usado en su aplicación), que se puede elegir para. El recolector de basura y luego, con el tiempo, limpiar su objeto, pero cuando esto sucede no es algo que (por lo general) de control.

Sólo la confianza de que con el tiempo se limpiaron. Esta es la belleza de C # (y .NET en general) -. La gestión, y la preocupación, de esto se maneja para usted


Editar: Después de algunas pruebas, parece que la ventana contiene una referencia a la UIElement hasta el siguiente pase diseño. Puede forzar a que esto ocurra mediante la adición de una llamada a:

this.UpdateLayout();

Después de la eliminación del elemento (s) de la lona de los niños. Esto hará que los objetos estén disponibles para GC.

Hay 3 generaciones de recolección de basura en C #, por lo que incluso si no hay referencias a los objetos, podría tomar 3 recolecciones de elementos para liberarlos.

Puede utilizar el GC.Collect () 's parámetro para forzar una tercera generación de la recolección de basura,
Sin embargo, la mejor approuch es no llamar GC.Collect () usted mismo,
en lugar de utilizar la interfaz IDisposable y los niños se unen a un ObservableCollection y cuando llegue un evento CollectionChanged Dispose () de los objetos eliminados.

Se puede encontrar este interesante. Descubrí recientemente que x: Nombre de marcado tiendas de extensión, en referencia a la UIElement en el control de los padres en un diccionario introducido por el nombre de la cadena.

Cuando se quita el UIElement de su padre, el diccionario mantiene una referencia al control.

  

Hay una entrada en el blog / vídeo de la depuración de la pérdida de memoria aquí: WPF   x: Nombre pérdida de memoria

La solución es no utilizar x: Nombre o para asegurar que los controles que se mantienen vivas por x:. Nombre se borran a cabo a fin de no consumir demasiada memoria antes de una sección del árbol visual se recoge

Actualización: cancelar el registro de una clase llamada utilizando el 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! 

Hemos tenido el mismo problema y también pensamos que esta puede ser la razón. Pero analizamos nuestro proyecto utilizando herramientas de perfil de memoria y encontramos que no hay nada que ver con el Grid.Remove o Grid.RemoveAt. Así que creo que mi sugerencia es sólo echar un vistazo a su proyecto en la herramienta de perfiles de memoria y ver lo que está sucediendo dentro de su proyecto. espera que esto ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top