.NET Framework
Speicherverwaltung
Suche…
Bemerkungen
Leistungskritische Anwendungen in verwalteten .NET-Anwendungen können durch den GC stark beeinträchtigt werden. Wenn der GC ausgeführt wird, werden alle anderen Threads bis zum Abschluss angehalten. Aus diesem Grund wird empfohlen, die GC-Prozesse sorgfältig zu bewerten und festzulegen, wie sie bei der Ausführung minimiert werden sollen.
Nicht verwaltete Ressourcen
Wenn wir über die GC und den "Heap" sprechen, sprechen wir wirklich über den sogenannten verwalteten Heap . Objekte auf dem verwalteten Heap können auf Ressourcen zugreifen, die sich nicht auf dem verwalteten Heap befinden, z. B. beim Schreiben oder Lesen aus einer Datei. Unerwartetes Verhalten kann auftreten, wenn eine Datei zum Lesen geöffnet wird und dann eine Ausnahmebedingung auftritt, die das Schließen des Datei-Handles verhindert. Aus diesem Grund erfordert .NET, dass nicht verwaltete Ressourcen die IDisposable
Schnittstelle implementieren. Diese Schnittstelle verfügt über eine einzige Methode namens Dispose
ohne Parameter:
public interface IDisposable
{
Dispose();
}
Beim Umgang mit nicht verwalteten Ressourcen sollten Sie sicherstellen, dass sie ordnungsgemäß entsorgt werden. Sie können dies tun, indem Sie Dispose()
explizit in einem finally
Block oder mit einer using
Anweisung aufrufen.
StreamReader sr;
string textFromFile;
string filename = "SomeFile.txt";
try
{
sr = new StreamReader(filename);
textFromFile = sr.ReadToEnd();
}
finally
{
if (sr != null) sr.Dispose();
}
oder
string textFromFile;
string filename = "SomeFile.txt";
using (StreamReader sr = new Streamreader(filename))
{
textFromFile = sr.ReadToEnd();
}
Letzteres ist die bevorzugte Methode und wird beim Kompilieren automatisch auf das Erstere erweitert.
Verwenden Sie SafeHandle, wenn Sie nicht verwaltete Ressourcen umschließen
Wenn Sie Wrapper für nicht verwaltete Ressourcen schreiben, sollten Sie SafeHandle
eher als Unterklasse SafeHandle
anstatt IDisposable
und einen Finalizer selbst zu implementieren. Ihre SafeHandle
Unterklasse sollte so klein und einfach wie möglich sein, um die SafeHandle
zu minimieren. Dies bedeutet wahrscheinlich, dass Ihre SafeHandle-Implementierung ein internes Implementierungsdetail einer Klasse enthält, das diese umschließt, um eine verwendbare API bereitzustellen. Diese Klasse stellt sicher, dass Ihr nicht verwalteter Handle freigegeben wird, auch wenn ein Programm Ihre SafeHandle
Instanz SafeHandle
.
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;
}
}
Haftungsausschluss: In diesem Beispiel wird gezeigt, wie eine verwaltete Ressource mit SafeHandle
die IDisposable
für Sie implementiert und die Finalizer entsprechend konfiguriert. Es ist sehr verständlich und wahrscheinlich sinnlos, auf diese Weise einen Speicherplatz zuzuweisen.