Pregunta

¿Qué recursos deben limpiarse manualmente en C# ¿Y cuáles son las consecuencias de no hacerlo?

Por ejemplo, digamos que tengo el siguiente código:

myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
// Use Brush

Si no limpio el pincel usando el método de eliminación, ¿supongo que el recolector de basura libera la memoria utilizada al finalizar el programa?¿Es esto correcto?

¿Qué otros recursos necesito para limpiar manualmente?

¿Fue útil?

Solución

Técnicamente, todo lo que herede de IDisposable debe eliminarse de forma proactiva.Puede utilizar la declaración 'usar' para facilitar las cosas.

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

A veces verá un uso inconsistente de objetos derivados de IDisposable en el código de muestra de la documentación, así como en el código generado por herramientas (es decir,estudio visual).

Lo bueno de IDisposable es que te brinda la posibilidad de proactivamente liberar el recurso no administrado subyacente.A veces realmente quieres hacer esto; piensa en las conexiones de red y en los recursos de archivos, por ejemplo.

Otros consejos

Si no desechas algo, se limpiará cuando el recolector de basura note que no hay más referencias a él en tu código, lo que puede ocurrir después de algún tiempo.Para algo así, realmente no importa, pero para un archivo abierto probablemente sí.

En general, si algo tiene un método Dispose, debes llamarlo cuando hayas terminado con él o, si puedes, envolverlo en un using declaración:

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}
  • Maneja las estructuras de datos internas de Windows.
  • Conexiones de bases de datos.
  • Identificadores de archivos.
  • Conexiones de red.
  • Referencias COM/OLE.

La lista continua.

es importante llamar Dispose o incluso mejor aún, utiliza el using patrón.

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}

Si no desechas algo, se limpiará cuando el recolector de basura note que no hay más referencias a él, lo que puede ocurrir después de un tiempo.

En el caso de System.Drawing.Brush, Windows mantendrá las estructuras internas de Windows para el pincel cargadas en la memoria hasta que todos los programas liberen su control.

Las consecuencias de no deshacerse de sus IDisposables pueden variar desde un impacto insignificante en el rendimiento hasta el bloqueo de su aplicación.

El GC limpiará el objeto Brush en su ejemplo cuando lo desee.Pero su programa no habrá tenido el beneficio de ese poco de memoria adicional que habría obtenido si lo hubiera limpiado antes.Si está utilizando muchos objetos Brush, esto podría resultar significativo.El GC también es más eficiente a la hora de limpiar objetos si no han existido por mucho tiempo, porque es un recolector de basura generacional.

Por otro lado, las consecuencias de no eliminar los objetos de conexión de la base de datos podrían significar que se quedará sin conexiones de bases de datos agrupadas muy rápidamente y provocar que su aplicación falle.

Cualquier uso

using (new DisposableThing...
{
    ...
}

O, si necesita conservar una referencia a un IDisposable en su objeto durante toda su vida, implemente IDisposable en su objeto y llame al método Dispose de IDisposable.

class MyClass : IDisposable
{
    private IDisposable disposableThing;

    public void DoStuffThatRequiresHavingAReferenceToDisposableThing() { ... }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    //etc... (see IDisposable on msdn)

}

Generalmente, cualquier cosa que implemente IDisposable debería hacer que usted haga una pausa e investigue el recurso que está utilizando.

La GC solo ocurre cuando hay presión de memoria, por lo que no se puede predecir cuándo.Aunque una descarga del AppDomain ciertamente lo activará.

Como otros han dicho, usar es tu amigo.escribí esta entrada de blog sobre cómo implementar IDisposable de una manera bastante sencilla y menos propensa a errores al tener en cuenta las partes más importantes.

Un truco que uso cuando no puedo recordar si un objeto determinado es un recurso desechable es escribir ".Dispose" (¡como máximo!) después de la declaración para que Intellisense lo verifique por mí:

MemoryStream ms = new MemoryStream().Dispose

Luego elimine .Dispose y use la directiva using():

using(MemoryStream ms = new MemoryStream())
{
  ...
}

Bueno, siempre que utilice la versión administrada de los recursos y no llame a las API de Windows usted mismo, todo estará bien.Sólo preocúpese por tener que eliminar/destruir un recurso cuando lo que obtiene es un IntPtr, ya que en .NET se conocen "identificadores de Windows" (y muchas otras cosas), y no un objeto.

Por cierto, el recurso (como cualquier otro objeto .NET) se marcará para su recopilación tan pronto como salga del contexto actual, por lo que si crea el Pincel dentro de un método, se marcará cuando salga de él.

Si está gestionado (es decir,parte del marco) no necesita preocuparse por eso.Si implementa IDisposable simplemente envuélvalo en un using bloquear.

Si desea utilizar recursos no administrados, debe leer sobre los finalizadores y la implementación de IDisposable usted mismo.

Hay muchos más detalles debajo esta pregunta

En primer lugar, al finalizar el programa, puede asumir que la memoria utilizada por el proceso se eliminará con el proceso mismo.

Al utilizar dispose o destructor in.net, se debe comprender que el momento en que el GC llama a la función dispose no es determinista.Es por eso que se recomienda usar o llamar a dispose explícitamente.

Cuando se utilizan recursos como archivos, se deben liberar objetos de memoria como semáforos y recursos que se encuentran fuera del mundo administrado de .net.

SolidBrush, por ejemplo, debe desecharse porque es un objeto GDI y vive fuera del mundo .net.

El recolector de basura no solo se libera al finalizar el programa, de lo contrario no sería realmente útil (en cualquier sistema operativo decente/reciente, cuando el proceso sale, el sistema operativo limpia automáticamente toda su memoria de todos modos).

Una de las grandes ventajas de C# en comparación con C/C++ es que no tiene que preocuparse por liberar objetos asignados (al menos la mayor parte del tiempo);el gc lo hace cuando el tiempo de ejecución lo decide (varias estrategias sobre cuándo y cómo hacerlo).

El gc no se ocupa de muchos recursos:archivos, recursos relacionados con subprocesos (bloqueos), conexiones de red, etc.

Un lugar donde hay que tener cuidado son los objetos que mirar Pequeños para GC pero no lo son...En la API de SharePoint, por ejemplo, el objeto SPWeb ocupa poco espacio en lo que respecta al GC y, por lo tanto, tendrá baja prioridad para la recopilación, pero realmente ha ocupado mucha memoria (en el montón, creo) que el GC no. No lo sé.Te encontrarás con algunos problemas de memoria divertidos si estás buscando un montón de estos, por ejemplo, ¡recuerda siempre usar o desechar!

En lugar de pensar que un objeto "contiene" recursos que necesitan ser liberados, es mejor pensar en términos de un objeto que ha alterado algo (¡posiblemente fuera de la computadora!) que lo sobrevivirá, de una manera que podría ser perjudicial si no deshecho ni "limpiado", pero que sólo el objeto puede limpiar.Si bien esta alteración comúnmente toma la forma de algún objeto concreto en un grupo marcado como "ocupado", su forma precisa no importa.Lo que importa es que los cambios deben deshacerse y el objeto contiene la información necesaria para hacerlo.

El recolector de basura manejará cualquier recurso administrado.En su ejemplo, el pincel se limpiará cuando el recolector de basura lo decida, lo que sucederá algún tiempo después de que la última referencia al pincel ya no sea válida.

Hay ciertas cosas que deben limpiarse manualmente, pero son punteros recuperados de fuentes no administradas, como llamadas DLL; sin embargo, nada dentro de .NET Framework necesita este tratamiento.

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