2011-05-05 14 views
7

Estoy creando nuevas matrices de bytes que GC no recopila y están viviendo en la memoria y aumentando los bytes privados. El siguiente código se ejecuta cada 10 segundos. ¿Cómo borro explícitamente la variable una vez que he terminado con ella?¿Cómo borro explícitamente el byte []

byte[] outputMessage = new byte[10000]; 
//Do some work here 
+2

Respecto a su comentario a Amadan: ¿Dónde se declara su variable? ¿Dentro del método del evento en el mensaje recibido o globalmente en tu clase, algoclase? – Markus

Respuesta

9

¿Cómo sabes que no se están recogiendo? El código que proporcione está bien, y debería ser elegible para la recopilación si no tiene referencias pendientes.

explícitamente, puede borrar una referencia por

outputMessage = null; 

y se puede hacer alusión al GC que debe hacer su trabajo con esto:

GC.Collect(); 

Sin embargo, no hay garantía de que su objeto se producirá obtener recogido, y manualmente jugando con el GC generalmente no es necesario.

Si está agregando un nuevo controlador de eventos todo el tiempo, ¿está eliminando alguno antiguo? Si no, entonces todavía conservan la referencia para ti.

EDIT: para mayor claridad, y para la nueva información por OP

+0

Estoy creando nuevas matrices de bytes en un controlador de eventos somethingclass.onreceivedmessage + = onreceivedmessage, donde somethingclass vive para siempre – Kiran

+0

Acepto que el código se ve bien tal como está, por lo que si no se recopila debe haber alguna otra referencia. Si ese es el caso, configure 'outputMessage = null' y la invocación' GC.Collect' no hará la diferencia. –

+0

Me han dicho que llamar a 'GC.Collect()' es [rara vez es una buena idea] (http://stackoverflow.com/questions/2414105/why-is-it-a-bad-practice-to-call -sistema-gc). Además, ¿el OP no dijo que GC se ejecuta no recoge la matriz? – zneak

2

Asegúrese de que tiene no hay referencias a la matriz. Examine que no tiene una asignación a otra variable que mantiene la matriz en la memoria.

¿Deja el foco de su outputMessage?
- Si está declarado dentro de un método: ¿lo dejas o tienes algún bucle infinito (intendente) y permaneces en él?
- Si se declara global dentro de un objeto de clase: ¿su clase completa permanece en la memoria haciendo referencia a esto?

+0

¿cómo se encuentra toda la referencia a un objeto en tiempo de ejecución? – user670800

2

Es difícil de decir con seguridad sin ver el contexto que se utiliza. A menos que se guarden las referencias a cada outputMessage, obtendrán la recolección de basura eventualmente cuando el GC decida ejecutar.

¿Qué estabas viendo para ver que los bytes privados seguían creciendo y nunca se reducirían? Además, ¿solo se ejecutaba con el depurador conectado o se ejecutaba en versión?

¿Realmente necesita crear una nueva matriz cada 10 segundos? Puede ser más rápido simplemente Array. Limpiar y reutilizar.

3

Considere esto: ¿Es posible encapsular su byte [] en una clase que implementa IDisposable? Después de su uso, puede deshacerse de su objeto llamando explícitamente a Dispose(). No estoy seguro de si esto lo guía a la solución, pero sería mi próximo intento.

+2

No veo cómo responde esto a la pregunta. Puedo implementar 'IDisposable' para ejecutar' MessageBox.Show ("Hello World!") ', Pero ¿cómo libera eso mi matriz de bytes? –

1

Cuando una matriz administrada sale del alcance, se marca para la recolección de elementos no utilizados. Si la matriz es de un tipo de valor, la desasignación de elementos es rápida, pero no ocurre hasta que la matriz se recopile. Recuerde, byte es un tipo de valor pero byte[] es un tipo de referencia.

Aquí hay una muestra rápida que ilustra:

void Main() 
{ 
    const int LOOPS = 5; 
    { 
     Console.WriteLine("When the arrays are kept inside the method's scope:"); 
     Console.WriteLine(String.Format("  GC Memory: {0:N0} bytes (starting memory)", GC.GetTotalMemory(false))); 
     for(int i = 0; i < LOOPS; i++) 
      this.AllocateArray(i); 
     Console.WriteLine(String.Format("  GC Memory: {0:N0} bytes (exited local scope)", GC.GetTotalMemory(false))); 
     Console.WriteLine(String.Format("  GC Memory: {0:N0} bytes (after GC collection ran)", GC.GetTotalMemory(true))); 

     Console.WriteLine("\nWhen the arrays are outside the method's scope:"); 
     Console.WriteLine(String.Format("  GC Memory: {0:N0} bytes (starting memory)", GC.GetTotalMemory(false))); 
     var arrays = new byte[LOOPS][]; 
     for(int i = 0; i < LOOPS; i++) 
      this.AllocateArray(i, arrays); 
     Console.WriteLine(String.Format("  GC Memory: {0:N0} bytes (exited local scope)", GC.GetTotalMemory(false))); 
     Console.WriteLine(String.Format("  GC Memory: {0:N0} bytes (after GC collection ran)", GC.GetTotalMemory(true))); 
     arrays[0][0] = 1; // Prevent the arrays from being optimized away 
    } 
    Console.WriteLine("\nAll scopes exited:"); 
     Console.WriteLine(String.Format("  GC Memory: {0:N0} bytes (before GC runs)", GC.GetTotalMemory(false))); 
     Console.WriteLine(String.Format("  GC Memory: {0:N0} bytes (after GC collection ran)", GC.GetTotalMemory(true))); 
} 

public void AllocateArray(int run) 
{ 
    var array = new byte[20000000]; 
    Thread.Sleep(100); // Simulate work.. 
    Console.WriteLine(String.Format("[{0}] GC Memory: {1:N0} bytes (local array allocated)", run+1, GC.GetTotalMemory(false))); 
    array[0] = 1; // Prevent the array from being optimized away 
} 

public void AllocateArray(int run, byte[][] arrays) 
{ 
    arrays[run] = new byte[20000000]; 
    Thread.Sleep(100); // Simulate work.. 
    Console.WriteLine(String.Format("[{0}] GC Memory: {1:N0} bytes (array allocated)", run+1, GC.GetTotalMemory(false))); 
} 

La salida de este se ve algo como esto (resultados exactos variarán):

Cuando las matrices se mantienen dentro del alcance del método:
          Memoria del GC: 24,576,232 bytes (memoria inicial)
[1] Memoria del GC: 45,002,324 bytes (matriz local asignada)
[2] GC memoria: 44,845,548 bytes (array local asignado)
[3] GC memoria: 64,574,296 bytes (array local asignado)
[4] Memoria GC: 64,959,472 bytes (array local asignado)
[5] memoria GC: 44,675,340 bytes (array local asignado)
          GC memoria: 44,675,340 bytes (ámbito local salido)
          GC memoria: 24,347,296 bytes (después de la recogida GC RAN)

Cuando las matrices están fuera del alcance del método:
          GC memoria: 24,355,488 bytes (de memoria inicial)
[1] GC de memoria: 44,467,612 bytes (array asignado)
[2] Memoria GC : 64,681,980 bytes (array asignados)
[3] GC de memoria: 85,493,004 bytes (array asignado)
[4] de memoria GC: 104,442,028 bytes (array asignado)
[5] GC de memoria: 124,450,236 bytes (array asignado)
          GC memoria: 124,450,236 bytes (salido de ámbito local)
          GC memoria: 124,357,588 bytes (después de la recolección GC corrió)

Todos los ámbitos salieron:
          GC Memoria: 124,365,780 bytes (antes de que se ejecute GC)
          GC memoria: 24,356,996 bytes (después corrió colección GC)

Para resolver el problema:

  1. Asegúrese de que no se aferran a cualquier referencia a los byte[] s. Los bytes no se borrarán hasta que todas las referencias a la matriz hayan desaparecido y esté completamente fuera del alcance.
  2. Llamar explícitamente al GC.Collect() después de que haya abandonado el alcance de la matriz de bytes.Una vez que está fuera de alcance, byte[] se borrará por sí solo pero puede indicarle que se ejecute en lugar de esperar.
Cuestiones relacionadas