2010-04-27 27 views
8

Dado que C# utiliza la recolección de basura. Cuándo es necesario usar. ¿Desea liberar la memoria?asignación de memoria C# y patrones de desasignación

Me doy cuenta de que hay algunas situaciones, así que intentaré enumerar las que se me ocurren.

  1. Si cierro un Formulario que contiene un objeto de tipo GUI, ¿se desreferencian esos objetos y, por lo tanto, se recopilarán?
  2. Si creo un objeto local utilizando new, ¿debo .Disfáltelo antes de que el método salga o simplemente deje que el GC se encargue de él? ¿Cuál es la buena práctica en este caso?
  3. ¿Hay momentos en los que forzar un GC es comprensible?
  4. ¿Los eventos son recopilados por el GC cuando se recopila su objeto?
+0

posible duplicado de http://stackoverflow.com/questions/2714811/is-there-a-common-practice-how-to-make-freeing-memory-for-garbage-collector-easie –

+0

También, duplicado de : http://stackoverflow.com/questions/331786/since-net-has-a-garbage-collector-why-do-we-need-finalizers-destructors-dispose Consulte también: http://stackoverflow.com/questions/1090451/net-garbage-collector-basics http://stackoverflow.com/questions/1729289/net-garbage-collector-mystery http://stackoverflow.com/questions/298261/do-event-handlers-stop-garbage -collection-from-occuring http://stackoverflow.com/questions/298261/do-event-handlers-stop-garbage-collection-from-occuring http://stackoverflow.com/questions/888280/ http: // stackoverflow .com/questions/371109/ –

+0

Generalmente IDisposable se implementa para recursos no administrados que no se devolverán, cerrarán ni utilizarán de manera óptima cuando el objec t es limpiado por el GC - el objeto administrado siempre es limpiado por GC. Ver IDisposable @ http: // msdn.microsoft.com/en-us/library/system.idisposable.aspx Para el n. ° 2, el GC se encarga de los objetos en el código administrado ya sea que llame a Dispose() o no. # 1 y los "objetos del tipo de GUI" incorporados se recopilarán si llama a Dispose() o no. También vea http://msdn.microsoft.com/en-us/magazine/bb985010.aspx –

Respuesta

10

En teoría, si ha definido correctamente conjunto de componentes, nunca debería ser necesario llamar a Dispose() en sus objetos, como el finalizador debe finalmente cuidar de él.

Dicho esto, cada vez que utilice un objeto que implementa IDisposable, es una buena práctica llamar a Dispose() en el objeto tan pronto como haya terminado de trabajar con él.

Para algunos de sus puntos específicos:

1) Si usted sabe que está "hecho" con el formulario, puede llamar a Dispose() en él. Esto obligará a una limpieza en ese momento en el recursos no administrados asociados con el formulario.

2) En este caso: si el objeto es sólo utilizado en ese método, utilizar el "uso" en su lugar:

using (MyObject myObject = new MyObject()) 
{ 
    // use your object 
} // It'll be disposed of here for you 

3) Hay razones raras de hacer esto, pero en general, no.

4) Los eventos son un delegado: la memoria asociada con el delegado se recopilará después de que el delegado se desrootee, lo que normalmente ocurre cuando los objetos en cuestión se desrojan.

+0

Utilizo el patrón using() {} para todos los recursos de tipo IO. Comenzaré a usarlo para que todos los objetos desechables sigan un patrón consistente. Gracias por tu respuesta. – Neal

2

mirada a esta pregunta:

Is there a common practice how to make freeing memory for Garbage Collector easier in .NET?

Si la clase crea una instancia de la interfaz IDisposable, que (probablemente) significa que no tiene los recursos del sistema que tienen que ser eliminados directamente. Una forma fácil de lograrlo es utilizar el uso de palabras clave, como en:

using(var g = Graphics.FromBitmap(bmp)) 
{ 
    //Do some stuff with the graphics object 
} 

por la respuesta de @ Matt S en esa pregunta que se hace referencia.

Para sus preguntas:

  1. Si se instancia un objeto que tiene IDisposable, tendrá que deshacerse de él cuando se cierra el formulario. Eso es complicado en WPF y directo en Winforms, ya que los diálogos de winforms tienen métodos de Dispose. Para WPF, he resuelto el problema manteniendo la clase WPF oculta, se llama método de disposición que elimina todos los objetos (como los puertos seriales) y luego establece la clase WPF en nulo.
  2. No. Deje que el GC se encargue de eso.
  3. Creo que sí, pero recibí comentarios negativos :) Cuando hice asignaciones muy grandes, obligar a GC a eliminarlos es, sí, una buena idea.
  4. No estoy seguro. Creo que los eventos son, en sí mismos, objetos, por lo que se recopilarán cuando ya no se usen.
+0

su respuesta # 2 parece estar en conflicto con la respuesta de todos los demás. ¿Por qué dices que el GC se encargue de eso? ¿También parece estar en conflicto con tu declaración original? – Neal

+0

Si solo hace un objeto usando nuevo, pero no implementa la interfaz IDisposable, deje que el GC se encargue de ello. Pero, si implementa IDisposable, debe deshacerse de él antes de dejarlo ir, como se muestra en el n. ° 1. Si declara una nueva matriz de entradas, int no implementa IDisposable, por lo que puede dejar que el gc se encargue de ello. – mmr

3

Debe llamar al Dispose en cada clase que implementa IDisposable. Si no necesita ser Dispose ed, entonces no implementaría IDisposable.

En cuanto a sus otras preguntas:

  1. Cuando se agrega un control a la colección del Formulario Controls, entonces el control se dispondrán de forma automática cuando se cierra el formulario, por lo que no hay nada que hay que hacer allí.
  2. Si el objeto implementa IDisposable, debe llamar al Dispose. Por ejemplo, si va al new FileStream(...), FileStream necesita eliminarse, ya que implementa IDisposable. Sugeriría que leas en el constructo using en C#, lo que facilita el manejo de los objetos IDisposable.
  3. En realidad, el 99.99% de las veces, el recolector de basura sabrá cuándo es el mejor momento para funcionar. Es uno de esos, "sabrás cuando lo necesites" tipo de situaciones.
  4. Cuando ya no se hace referencia al objeto que contiene el evento, lógicamente cualquier referencia de objeto contenida en el evento ya no se referencia y estará disponible para su recopilación.
+0

# 1: cierto, pero ¿y si el objeto se agrega en el momento del diseño pero no se agrega a la colección del control? ¿Seguirá siendo liberado cuando el formulario esté cerrado? # 2: De hecho, casi siempre implemento el patrón using() {} cuando trato con recursos de IO. # 4: He leído muchas instancias en las que la propiedad de evento no eliminado eliminará la memoria. O mejor dicho, no liberar la memoria. Me doy cuenta de que esto puede ser solo una referencia que es insignificante. – Neal

+0

En el n. ° 4, cuando el objeto * que contiene * el evento ya no sea una referencia, un objeto que haga referencia al evento en sí mismo también dejará de estar referenciado. El problema surge cuando agrega un controlador a un evento, el evento contiene una referencia a ese objeto: por lo tanto, el objeto no se recuperará hasta que se recupere el * evento * o se anule la suscripción manualmente. Para la mayoría de las cosas de WinForms, el controlador de eventos generalmente está en el formulario que lo contiene, por lo que generalmente no es un problema. –

+0

ah veo que tiene sentido. Gracias por la aclaración. – Neal

0

Si está utilizando un objeto IDisposable, considere utilizar la declaración using para ocuparse automáticamente de deshacerse de usted.

1

Como dijo Reed Copsey, generalmente no es necesario llamar a Dispose.

Un posible caso que puede estar creando su problema es que un objeto estático contiene referencias de otros objetos que ya no se usan en ningún otro lado. El siguiente código muestra un ejemplo:

Form_Load(...) 
    MyState.Instance.AddressChanged += this.User_AddressChanged; 
End 

Si por alguna razón, cuando se descarga la forma, el código no anular el registro del controlador de eventos, la instancia de forma seguirá siendo referenciado por el objeto de estado.

Cuestiones relacionadas