7
votes

Comment puis-je expliquer explicitement l'octet []

Je crée de nouveaux tableaux d'octets qui ne sont pas collectés par GC et vivent en mémoire et augmentent les octets privés. Le code ci-dessous est exécuté toutes les 10 secondes. Comment puis-je expliquer explicitement la variable après avoir terminé avec elle? XXX


1 commentaires

En ce qui concerne votre commentaire à Amadan: Où est déclaré votre variable? À l'intérieur de la méthode d'événement OnReceEvedMessage ou globalement dans votre classe Quelqueclass?


6 Réponses :


10
votes

Comment savez-vous qu'ils ne sont pas collectés? Le code que vous fournissez est correct et il devrait devenir éligible à la collecte si vous n'avez pas de références en pelage.

explicitement, vous pouvez effacer une référence par P>

GC.Collect();


7 commentaires

Je crée de nouveaux tableaux d'octets dans un gestionnaire d'événements Quelqueclass.EnreceivedMessage + = onreceedMessage, où quelque chose ne vit pas pour toujours


Je conviens que le code a l'air bien, comme si ce n'est pas collecté, il doit y avoir une autre référence. Si tel est le cas, réglage sortieMessage = null et appeler gc.collect ne fera pas une différence.


On m'a dit que Calling gc.collect () est rarement une bonne idée . En outre, l'OP n'a-t-il pas dit que GC est exécuté ne recueille pas le tableau?


Il y a eu des rapports de fuites de mémoire dus aux gestionnaires d'événements et aux références détenues à cause d'eux. Je ne sais pas si la mémoire que vous allez faire face est liée à cela. Vous pouvez jeter un coup d'œil ici Stackoverflow.com/ Questions / 1843270 / ... blogs.msdn.com/b/tess/archive/2006/01/23/... blogs.msdn.com/b/abhinaba/ Archive / 2009/05/05 / ...


@Brian, @zneak: En effet, je pense que je ne me suis pas exprimé correctement. Les deux sont séparés: le nettoyage de sa variable n'expliquerait aucune autre référence. J'apparais juste comment vous pouvez expliquer explicitement toute référence avant même qu'il ne soit hors de portée, faites des choses manuellement. Bien sûr, laissez GC décider seul est une meilleure idée.


Le gestionnaire d'événements ne sera désabonné que lorsque le service Windows est arrêté. Le service fonctionne 24h / 24 et 7j / 7 et continue de recevoir des messages en continu.


Que diriez-vous d'utiliser Array.Resize () pour réduire explicitement le tableau? Cela devrait réduire l'empreinte mémoire.



2
votes

S'assurer que vous n'avez aucune référence à votre tableau. Examinez que vous n'avez pas d'affectation à une autre variable qui conserve la matrice en mémoire.

Laissez-vous le centre de votre sortieMessage?
- Si cela est déclaré à l'intérieur d'une méthode: laissez-vous la laisser ou avez-vous une boucle sans fin (intendant) et y rester?
- s'il est déclaré global à l'intérieur d'un objet de classe: votre classe complète reste-t-elle en mémoire par une référence à cela?


1 commentaires

Comment trouvez-vous toute référence à un objet au moment de l'exécution?



2
votes

Il est difficile de dire avec certitude sans voir le contexte que c'est utilisé dans. sauf si vous gardez des références à chaque sortieMessage, ils obtiendront des déchets collectés éventuellement chaque fois que le GC décide de fonctionner.

Que regardiez-vous pour voir que les octets privés ont continué à croître et ne se rétréciraient jamais? Vous étiez également uniquement avec le débogueur attaché ou étiez-vous en cours d'exécution?

Avez-vous vraiment besoin de créer un nouveau tableau toutes les 10 secondes? Cela pourrait être plus rapide pour simplement arrayer.clear et le réutiliser.


0 commentaires

2
votes

Considérez ceci: Est-il possible d'encapsuler votre octet [] dans une classe qui implémente Idisposable? Après utilisation, vous pouvez disposer de votre objet en appelant explicitement disposer (). Je ne sais pas si cela vous guide à la solution, mais ce serait ma prochaine tentative.


2 commentaires

Je ne vois pas comment cela répond à la question. Je peux implémenter Idisposable pour exécuter MessageBox.show ("Hello World!") , mais comment libérez-le mon tableau d'octets?


l'octet [] est un type de référence. C'est une ressource gérée. Idisposable est utilisé pour des ressources non gérées telles que les poignées, les prises, le pointeur brut. Pas pour les ressources gérées.



2
votes

Lorsqu'un tableau géré quitte la portée, il est marqué pour la collecte des ordures. Si le tableau est d'une valeur de valeur, la répartition des articles est rapide mais ne se produit pas jusqu'à ce que le tableau soit collecté em>. N'oubliez pas que octet code> est un type de valeur mais octet [] code> est un type de référence.

Voici un échantillon rapide qui illustre: P>

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


0 commentaires

0
votes

Ce cas de test ne fonctionne que en mode de sortie. Je crée un tableau en utilisant une classe GUID (c'est facile). Il aurait 16 éléments.

[TestMethod]
public void ByteArrayReleasesMemoryWhenTheyGoOutOfScope()
{
    // *** WORKS ONLY IN RELEASE MODE ***
    // arrange
    var weakRef = new WeakReference(null);

    // easy way to generate byte array
    var byteArray = Guid.NewGuid().ToByteArray();
    weakRef.Target = byteArray;

    // act
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();

    // assert
    Assert.IsFalse(weakRef.IsAlive);
}


0 commentaires