Recherche…


Remarques

Les applications à performance critique dans les applications .NET gérées peuvent être gravement affectées par le GC. Lorsque le GC s'exécute, tous les autres threads sont suspendus jusqu'à la fin. Pour cette raison, il est recommandé d’évaluer soigneusement les processus du GC et de déterminer comment les réduire au minimum.

Ressources non gérées

Quand on parle du GC et du "tas", on parle vraiment de ce qu'on appelle le tas géré . Les objets sur le segment géré peuvent accéder aux ressources qui ne sont pas sur le segment de mémoire géré, par exemple lors de l'écriture ou de la lecture d'un fichier. Un comportement inattendu peut se produire lorsqu'un fichier est ouvert pour être lu et qu'une exception se produit, empêchant le descripteur de fichier de se fermer normalement. Pour cette raison, .NET exige que les ressources non managées implémentent l'interface IDisposable . Cette interface a une seule méthode appelée Dispose sans paramètres:

public interface IDisposable
{
    Dispose();
} 

Lorsque vous manipulez des ressources non gérées, vous devez vous assurer qu'elles sont correctement éliminées. Vous pouvez le faire en appelant explicitement Dispose() dans un bloc finally ou avec une instruction using .

StreamReader sr; 
string textFromFile;
string filename = "SomeFile.txt";
try 
{
    sr = new StreamReader(filename);
    textFromFile = sr.ReadToEnd();
}
finally
{
    if (sr != null) sr.Dispose();
}

ou

string textFromFile;
string filename = "SomeFile.txt";

using (StreamReader sr = new Streamreader(filename))
{
    textFromFile = sr.ReadToEnd();
}

Cette dernière méthode est la méthode préférée et s’étend automatiquement à la précédente lors de la compilation.

Utilisez SafeHandle lorsque vous encapsulez des ressources non managées

Lorsque vous écrivez des wrappers pour des ressources non gérées, vous devez sous- SafeHandle plutôt que d'essayer d'implémenter IDisposable et un finaliseur vous-même. Votre sous-classe SafeHandle doit être aussi petite et simple que possible pour minimiser les risques de fuite. Cela signifie probablement que votre implémentation SafeHandle serait un détail d'implémentation interne d'une classe qui l'enveloppe pour fournir une API utilisable. Cette classe garantit que, même si un programme SafeHandle votre instance SafeHandle , votre SafeHandle non géré est libéré.

using System.Runtime.InteropServices;

class MyHandle : SafeHandle
{
    public override bool IsInvalid => handle == IntPtr.Zero;
    public MyHandle() : base(IntPtr.Zero, true)
    { }

    public MyHandle(int length) : this()
    {
        SetHandle(Marshal.AllocHGlobal(length));
    }

    protected override bool ReleaseHandle()
    {
        Marshal.FreeHGlobal(handle);
        return true;
    }
}

Disclaimer: Cet exemple est une tentative pour montrer comment protéger une ressource gérée avec SafeHandle qui implémente IDisposable pour vous et qui configure les finaliseurs de manière appropriée. C'est très artificiel et probablement inutile d'allouer un morceau de mémoire de cette manière.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow