.NET Framework
Gestion de la mémoire
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.