.NET Framework
Geheugen management
Zoeken…
Opmerkingen
Prestatiekritieke applicaties in beheerde .NET-applicaties kunnen ernstig worden beïnvloed door de GC. Wanneer de GC wordt uitgevoerd, worden alle andere threads opgeschort totdat deze zijn voltooid. Om deze reden wordt het aanbevolen om de GC-processen zorgvuldig te evalueren en te bepalen hoe deze kunnen worden geminimaliseerd.
Onbeheerde bronnen
Als we het hebben over de GC en de "heap", hebben we het echt over wat de managed heap wordt genoemd . Objecten op de beheerde heap hebben toegang tot bronnen die zich niet op de beheerde heap bevinden, bijvoorbeeld bij het schrijven naar of lezen uit een bestand. Onverwacht gedrag kan optreden wanneer een bestand wordt geopend om te worden gelezen en vervolgens een uitzondering optreedt waardoor de bestandsingang niet zoals normaal wordt gesloten. Om deze reden vereist .NET dat onbeheerde bronnen de IDisposable
interface IDisposable
. Deze interface heeft een enkele methode genaamd Dispose
zonder parameters:
public interface IDisposable
{
Dispose();
}
Wanneer u onbeheerde bronnen hanteert, moet u ervoor zorgen dat deze correct worden verwijderd. U kunt dit doen door expliciet te bellen Dispose()
in een finally
blok, of met using
verklaring.
StreamReader sr;
string textFromFile;
string filename = "SomeFile.txt";
try
{
sr = new StreamReader(filename);
textFromFile = sr.ReadToEnd();
}
finally
{
if (sr != null) sr.Dispose();
}
of
string textFromFile;
string filename = "SomeFile.txt";
using (StreamReader sr = new Streamreader(filename))
{
textFromFile = sr.ReadToEnd();
}
De laatste is de voorkeursmethode en wordt tijdens compilatie automatisch naar de eerste uitgebreid.
Gebruik SafeHandle bij het inpakken van onbeheerde bronnen
Wanneer u wrappers schrijft voor onbeheerde bronnen, moet u SafeHandle
in een subklasse SafeHandle
plaats van zelf IDisposable
en een finalizer te implementeren. Uw SafeHandle
subklasse moet zo klein en eenvoudig mogelijk zijn om de kans op een lek in de handgreep te minimaliseren. Dit betekent waarschijnlijk dat uw SafeHandle-implementatie een intern implementatiedetail van een klasse zou zijn die deze omwikkelt met een bruikbare API. Deze klasse zorgt ervoor dat, zelfs als een programma uw SafeHandle
instantie lekt, uw onbeheerde handle wordt vrijgegeven.
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: dit voorbeeld is een poging om te laten zien hoe u een beheerde bron SafeHandle
met SafeHandle
die IDisposable
voor u implementeert en de finalisten op de juiste manier configureert. Het is heel gekunsteld en waarschijnlijk zinloos om op deze manier een stuk geheugen toe te wijzen.