Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Metoda Dispose je primárně implementována pro uvolnění nespravovaných prostředků. Při práci s členy instance, které jsou implementace IDisposable, je běžné kaskádové volání Dispose. Existují další důvody pro implementaci Dispose, například uvolnění paměti, která byla přidělena, odebrání položky přidané do kolekce nebo signál uvolnění zámku, který byl získán.
Systém .NET garbage collector nepřiděluje ani neuvolňuje nespravovanou paměť. Vzor pro likvidaci objektu, označovaný jako dispose vzor, zajišťuje řízení doby života objektu. Vzor Dispose se používá pro objekty, které implementují rozhraní IDisposable. Tento vzor je běžný při interakci s popisovači souborů a rour, popisovači registru, popisovači čekání nebo ukazateli na bloky nespravované paměti, protože ten správce paměti nemůže uvolnit nespravované objekty.
Aby bylo možné zajistit, aby prostředky byly vždy správně vyčištěny, měla by být metoda Dispose idempotentní, aby byla volána vícekrát bez vyvolání výjimky. Další vyvolání Dispose by navíc nemělo dělat nic.
Příklad kódu zadaný pro metodu GC.KeepAlive ukazuje, jak proces uvolňování paměti může způsobit, že se finalizátor může spustit, i když nespravovaný odkaz na objekt nebo jeho členy je stále používán. Je vhodné využít GC.KeepAlive, aby byl objekt nezpůsobilý pro garbage collection od začátku aktuální rutiny do bodu, kde je tato metoda volána.
Spropitné
Pokud jde o injektování závislostí, při registraci služeb v IServiceCollectionse doba života služby implicitně spravuje vaším jménem. IServiceProvider a odpovídající IHost orchestrují čištění prostředků. Konkrétně jsou implementace IDisposable a IAsyncDisposable správně odstraněny na konci své stanovené životnosti.
Další informace naleznete v tématu Injektování závislostí v .NET.
Kaskádová volání dispose
Pokud vaše třída vlastní instanci jiného typu, který implementuje IDisposable, obsahující třída by měla také implementovat IDisposable. Obvykle třída, která vytvoří instanci IDisposable implementace a uloží ji jako člena instance (nebo vlastnost), je také zodpovědná za vyčištění. To pomáhá zajistit, aby odkazované uvolnitelné typy měly možnost předvídatelně provést vyčištění pomocí metody Dispose. V následujícím příkladu je třída sealed
(nebo NotInheritable
v jazyce Visual Basic).
using System;
public sealed class Foo : IDisposable
{
private readonly IDisposable _bar;
public Foo()
{
_bar = new Bar();
}
public void Dispose() => _bar.Dispose();
}
Public NotInheritable Class Foo
Implements IDisposable
Private ReadOnly _bar As IDisposable
Public Sub New()
_bar = New Bar()
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
_bar.Dispose()
End Sub
End Class
Spropitné
- Pokud má vaše třída IDisposable pole nebo vlastnost, ale ji nevlastní, třída nemusí implementovat IDisposable. Obvykle se třídou, která vytváří a ukládá podřízený objekt IDisposable, stává i jeho vlastníkem, ale v některých případech lze vlastnictví převést na jiný typ IDisposable.
- Existují případy, kdy můžete chtít provést
null
-kontrolu ve finalizátoru (která zahrnuje metoduDispose(false)
, kterou spustí finalizátor). Jedním z hlavních důvodů je, že si nejste jistí, jestli se instance plně inicializovala (například výjimka může být vyvolána v konstruktoru).
Dispose() a Dispose(bool)
Rozhraní IDisposable vyžaduje implementaci jedné metody bez parametrů Dispose. Všechny nezapečetěné třídy by také měly mít přetíženou metodu Dispose(bool)
.
Podpisy metod jsou:
-
public
nevirtuální (NotOverridable
v jazyce Visual Basic) (IDisposable.Dispose implementace). -
protected virtual
(Overridable
v jazyce Visual Basic)Dispose(bool)
.
Metoda Dispose()
Vzhledem k tomu, že metoda Dispose
, která je bez parametrů a non-virtual (NotOverridable
v jazyce Visual Basic), je volána, když už není potřeba (příjemcem typu), je jejím účelem uvolnit nespravované prostředky, provést obecné vyčištění a indikovat, že finalizátor, pokud existuje, nemusí být spuštěn. Uvolnění skutečné paměti přidružené ke spravovanému objektu je vždy úlohou garbage collectoru. Z tohoto důvodu má standardní implementaci:
public void Dispose()
{
// Dispose of unmanaged resources.
Dispose(true);
// Suppress finalization.
GC.SuppressFinalize(this);
}
Public Sub Dispose() _
Implements IDisposable.Dispose
' Dispose of unmanaged resources.
Dispose(True)
' Suppress finalization.
GC.SuppressFinalize(Me)
End Sub
Metoda Dispose
provede veškeré vyčištění objektů, takže garbage collector už nemusí volat přepsání objektů pomocí Object.Finalize. Proto volání metody SuppressFinalize zabraňuje garbage collectoru ve spuštění finalizátoru. Pokud typ nemá žádný finalizátor, volání GC.SuppressFinalize nemá žádný vliv. Skutečné vyčištění provádí přetěžování dané metody Dispose(bool)
.
Přetížení metody Dispose(bool)
V přetížení označuje parametr disposing
typu Boolean, zda volání metody pochází z metody Dispose (její hodnota je true
) nebo z ukončovací metody (její hodnota je false
).
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
// Dispose managed state (managed objects).
// ...
}
// Free unmanaged resources.
// ...
_disposed = true;
}
Protected Overridable Sub Dispose(disposing As Boolean)
If disposed Then Exit Sub
If disposing Then
' Free managed resources.
' ...
End If
' Free unmanaged resources.
' ...
disposed = True
End Sub
Důležitý
Parametr disposing
by měl být při zavolání z finalizátoru false
a při zavolání z metody true
IDisposable.Dispose. Jinými slovy, je to true
, pokud je volán deterministicky, a false
, pokud je volán nedeterministicky.
Tělo metody se skládá ze tří bloků kódu:
Blok pro podmíněné vrácení, pokud je objekt již zlikvidován.
Podmíněný blok, který uvolní spravované prostředky. Tento blok se spustí, pokud je hodnota
disposing
true
. Mezi spravované prostředky, které uvolní, patří:- Spravované objekty, které implementují IDisposable. Podmíněný blok lze použít k volání implementace Dispose (kaskádová dispose). Pokud jste k zabalení nespravovaného prostředku použili odvozenou třídu System.Runtime.InteropServices.SafeHandle, měli byste zde zavolat metodu SafeHandle.Dispose().
- Spravované objekty, které spotřebovávají velké množství paměti nebo využívají málo prostředků. Přiřaďte velké spravované objektové odkazy na
null
, aby byly s větší pravděpodobností nedostupnější. Tím se uvolní rychleji, než kdyby byly uvolněny nedeterministicky.
Blok, který uvolní nespravované prostředky. Tento blok se spustí bez ohledu na hodnotu parametru
disposing
.
Pokud volání metody pochází z finalizátoru, měl by se spustit pouze kód, který uvolní nespravované prostředky. Implementátor je odpovědný za to, aby falešná cesta neinteragovala se spravovanými objekty, které mohly být ukončeny. To je důležité, protože pořadí, ve kterém garbage collector zpracovává spravované objekty během finalizace, je nedeterministické.
Implementace vzoru Dispose
Všechny nezapečetěné třídy (nebo třídy jazyka Visual Basic, které nejsou upraveny jako NotInheritable
), by se měly považovat za potenciální základní třídu, protože by mohly být zděděné. Pokud implementujete vzor Dispose pro libovolnou potenciální základní třídu, musíte do své třídy přidat následující metody:
- Implementace Dispose, která volá metodu
Dispose(bool)
. - Metoda
Dispose(bool)
, která provádí skutečné vyčištění. - Pokud se vaše třída zabývá nespravovanými prostředky, buď přepište metodu Object.Finalize, nebo zabalte nespravovaný prostředek pod třídu SafeHandle.
Důležitý
Finalizátor (přepsání Object.Finalize) se vyžaduje pouze v případě, že přímo odkazujete na nespravované prostředky. Jedná se o vysoce pokročilý scénář, kterému se obvykle můžete vyhnout:
- Pokud vaše třída odkazuje pouze na spravované objekty, je stále možné, aby třída implementuje vzor Dispose. Není nutné implementovat finalizér.
- Pokud potřebujete řešit nespravované prostředky, důrazně doporučujeme zabalit nespravovaný IntPtr popisovač do SafeHandle. SafeHandle poskytuje finalizátor, takže si ho nemusíte psát sami. Další informace najdete v odstavci Bezpečné popisovače.
Základní třída se spravovanými prostředky
Tady je obecný příklad implementace modelu Dispose pro základní třídu, která vlastní pouze spravované prostředky.
using System;
using System.IO;
public class DisposableBase : IDisposable
{
// Detect redundant Dispose() calls.
private bool _isDisposed;
// Instantiate a disposable object owned by this class.
private Stream? _managedResource = new MemoryStream();
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
_isDisposed = true;
if (disposing)
{
// Dispose managed state.
_managedResource?.Dispose();
_managedResource = null;
}
}
}
}
Imports System.IO
Public Class DisposableBase
Implements IDisposable
' Detect redundant Dispose() calls.
Private _isDisposed As Boolean
' Instantiate a disposable object owned by this class.
Private _managedResource As Stream = New MemoryStream()
' Public implementation of Dispose pattern callable by consumers.
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
' Protected implementation of Dispose pattern.
Protected Overridable Sub Dispose(disposing As Boolean)
If Not _isDisposed Then
_isDisposed = True
If disposing Then
' Dispose managed state.
_managedResource?.Dispose()
_managedResource = Nothing
End If
End If
End Sub
End Class
Poznámka
Předchozí příklad používá fiktivní objektMemoryStream k ilustraci vzoru. Místo toho lze použít jakýkoli IDisposable.
Základní třída s nespravovanými prostředky
Tady je příklad implementace vzoru Dispose pro základní třídu, která přepíše Object.Finalize, aby se vyčistily nespravované prostředky, které vlastní. Příklad také ukazuje způsob, jak implementovat Dispose(bool)
bezpečným způsobem. Synchronizace může být důležitá při práci s nespravovanými prostředky v aplikaci s více vlákny. Jak už bylo zmíněno dříve, jedná se o pokročilý scénář.
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
public class DisposableBaseWithFinalizer : IDisposable
{
// Detect redundant Dispose() calls in a thread-safe manner.
// _isDisposed == 0 means Dispose(bool) has not been called yet.
// _isDisposed == 1 means Dispose(bool) has been already called.
private int _isDisposed;
// Instantiate a disposable object owned by this class.
private Stream? _managedResource = new MemoryStream();
// A pointer to 10 bytes allocated on the unmanaged heap.
private IntPtr _unmanagedResource = Marshal.AllocHGlobal(10);
~DisposableBaseWithFinalizer() => Dispose(false);
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
// In case _isDisposed is 0, atomically set it to 1.
// Enter the branch only if the original value is 0.
if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) == 0)
{
if (disposing)
{
_managedResource?.Dispose();
_managedResource = null;
}
Marshal.FreeHGlobal(_unmanagedResource);
}
}
}
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Threading
Public Class DisposableBaseWithFinalizer
Implements IDisposable
' Detect redundant Dispose() calls in a thread-safe manner.
' _isDisposed == 0 means Dispose(bool) has not been called yet.
' _isDisposed == 1 means Dispose(bool) has been already called.
Private _isDisposed As Integer
' Instantiate a disposable object owned by this class.
Private _managedResource As Stream = New MemoryStream()
' A pointer to 10 bytes allocated on the unmanaged heap.
Private _unmanagedResource As IntPtr = Marshal.AllocHGlobal(10)
Protected Overrides Sub Finalize()
Dispose(False)
End Sub
' Public implementation of Dispose pattern callable by consumers.
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
' Protected implementation of Dispose pattern.
Protected Overridable Sub Dispose(disposing As Boolean)
' In case _isDisposed is 0, atomically set it to 1.
' Enter the branch only if the original value is 0.
If Interlocked.CompareExchange(_isDisposed, 1, 0) = 0 Then
If disposing Then
_managedResource?.Dispose()
_managedResource = Nothing
End If
Marshal.FreeHGlobal(_unmanagedResource)
End If
End Sub
End Class
Poznámka
- Předchozí příklad používá AllocHGlobal k přidělení 10 bajtů v nespravované haldě v konstruktoru a uvolnění vyrovnávací paměti v
Dispose(bool)
voláním FreeHGlobal. Toto je fiktivní přidělení určené pro ilustrační účely. - Opět se doporučuje vyhnout implementaci finalizátoru. Vizte Implementaci vzoru Dispose s použitím vlastního bezpečnostního popisovače pro ekvivalent předchozího příkladu, který deleguje nedeterministickou finalizaci a synchronizaci na SafeHandle.
Spropitné
V jazyce C# implementujete finalizaci tak, že poskytnete finalizační konstruktor , nikoli přepsáním Object.Finalize. V jazyce Visual Basic vytvoříte finalizér s Protected Overrides Sub Finalize()
.
Implementace vzoru Dispose Pattern pro odvozenou třídu
Třída odvozená z třídy, která implementuje IDisposable rozhraní by neměla implementovat IDisposable, protože základní třída implementace IDisposable.Dispose je zděděna jeho odvozenými třídami. Pokud chcete vyčistit odvozenou třídu, zadejte následující:
-
protected override void Dispose(bool)
metoda, která přepíše metodu základní třídy a provádí skutečné vyčištění odvozené třídy. Tato metoda musí také volat metodubase.Dispose(bool)
(MyBase.Dispose(bool)
v jazyce Visual Basic) a předat jí stav vystavení (bool disposing
parametr) jako argument. - Buď třída odvozená z SafeHandle, která obalí váš nespravovaný prostředek (doporučeno), nebo přepsání metody Object.Finalize. Třída SafeHandle poskytuje finalizér, který vás zbaví nutnosti jej programovat. Pokud zadáte finalizátor, musí volat přetíženou funkci
Dispose(bool)
s argumentemfalse
.
Tady je příklad běžného schématu pro implementaci vzoru Dispose pro odvozenou třídu, která používá bezpečnou rukojeť.
using System.IO;
public class DisposableDerived : DisposableBase
{
// To detect redundant calls
private bool _isDisposed;
// Instantiate a disposable object owned by this class.
private Stream? _managedResource = new MemoryStream();
// Protected implementation of Dispose pattern.
protected override void Dispose(bool disposing)
{
if (!_isDisposed)
{
_isDisposed = true;
if (disposing)
{
_managedResource?.Dispose();
_managedResource = null;
}
}
// Call base class implementation.
base.Dispose(disposing);
}
}
Imports System.IO
Public Class DisposableDerived
Inherits DisposableBase
' To detect redundant calls
Private _isDisposed As Boolean
' Instantiate a disposable object owned by this class.
Private _managedResource As Stream = New MemoryStream()
' Protected implementation of Dispose pattern.
Protected Overrides Sub Dispose(disposing As Boolean)
If Not _isDisposed Then
_isDisposed = True
If disposing Then
_managedResource?.Dispose()
_managedResource = Nothing
End If
End If
' Call base class implementation.
MyBase.Dispose(disposing)
End Sub
End Class
Poznámka
Předchozí příklad používá objekt SafeFileHandle k ilustraci vzoru; místo toho lze použít jakýkoli objekt odvozený z SafeHandle. Všimněte si, že se v příkladu nesprávně vytváří instance objektu SafeFileHandle.
Tady je obecný vzor pro implementaci vzoru Dispose pro odvozenou třídu, která přepisuje Object.Finalize:
using System.Threading;
public class DisposableDerivedWithFinalizer : DisposableBaseWithFinalizer
{
// Detect redundant Dispose() calls in a thread-safe manner.
// _isDisposed == 0 means Dispose(bool) has not been called yet.
// _isDisposed == 1 means Dispose(bool) has been already called.
private int _isDisposed;
~DisposableDerivedWithFinalizer() => Dispose(false);
// Protected implementation of Dispose pattern.
protected override void Dispose(bool disposing)
{
// In case _isDisposed is 0, atomically set it to 1.
// Enter the branch only if the original value is 0.
if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) == 0)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
}
// Call the base class implementation.
base.Dispose(disposing);
}
}
Imports System.Threading
Public Class DisposableDerivedWithFinalizer
Inherits DisposableBaseWithFinalizer
' Detect redundant Dispose() calls in a thread-safe manner.
' _isDisposed == 0 means Dispose(bool) has not been called yet.
' _isDisposed == 1 means Dispose(bool) has been already called.
Private _isDisposed As Integer
Protected Overrides Sub Finalize()
Dispose(False)
End Sub
' Protected implementation of Dispose pattern.
Protected Overrides Sub Dispose(disposing As Boolean)
' In case _isDisposed is 0, atomically set it to 1.
' Enter the branch only if the original value is 0.
If Interlocked.CompareExchange(_isDisposed, 1, 0) = 0 Then
If disposing Then
' TODO: dispose managed state (managed objects).
End If
' TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
' TODO: set large fields to null.
End If
' Call the base class implementation.
MyBase.Dispose(disposing)
End Sub
End Class
Bezpečné úchyty
Psaní kódu pro finalizátor objektu je složitá úloha, která může způsobit problémy, pokud nejsou provedeny správně. Proto doporučujeme vytvořit System.Runtime.InteropServices.SafeHandle objekty místo implementace finalizátoru.
System.Runtime.InteropServices.SafeHandle je abstraktní spravovaný typ, který obaluje System.IntPtr identifikující nespravovaný prostředek. Ve Windows může jít o identifikaci popisovače a na Unixu o deskriptor souboru.
SafeHandle
poskytuje veškerou logiku potřebnou k tomu, aby byl tento prostředek uvolněn jednou a pouze jednou, a to buď při odstranění SafeHandle
, nebo při vyřazení všech odkazů na SafeHandle
a dokončení instance SafeHandle
.
System.Runtime.InteropServices.SafeHandle je abstraktní základní třída. Odvozené třídy poskytují konkrétní instance pro různé typy popisovačů. Tyto odvozené třídy ověřují, které hodnoty pro System.IntPtr jsou považovány za neplatné a jak přesně uvolnit popisovač. Například SafeFileHandle je odvozen od SafeHandle
k zabalení IntPtrs
, které identifikují otevřené držitele souborů a popisovače, a přepíše svou SafeHandle.ReleaseHandle() metodu k jejich zavření (prostřednictvím funkce close
na Unixu nebo funkce CloseHandle
ve Windows). Většina rozhraní API v knihovnách .NET, které vytvářejí nespravovaný prostředek, zabalí ho do SafeHandle
a vrátí SafeHandle
podle potřeby, místo předávání surového ukazatele zpět. V situacích, kdy pracujete s nespravovanou komponentou a získáte IntPtr
pro nespravovaný prostředek, můžete vytvořit vlastní typ SafeHandle
k jeho obalení. V důsledku toho potřebuje jen málo typů, které nejsouSafeHandle
, implementovat finalizátory. Většina implementací jednorázových vzorů končí pouze zabalením jiných spravovaných prostředků, z nichž některé můžou být SafeHandle
objekty.
Implementace vzorce Dispose pomocí vlastního bezpečného popisovače
Následující kód ukazuje, jak zpracovat nespravované prostředky implementací SafeHandle.
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
// Wraps the IntPtr allocated by Marshal.AllocHGlobal() into a SafeHandle.
class LocalAllocHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private LocalAllocHandle() : base(ownsHandle: true) { }
// No need to implement a finalizer - SafeHandle's finalizer will call ReleaseHandle for you.
protected override bool ReleaseHandle()
{
Marshal.FreeHGlobal(handle);
return true;
}
// Allocate bytes with Marshal.AllocHGlobal() and wrap the result into a SafeHandle.
public static LocalAllocHandle Allocate(int numberOfBytes)
{
IntPtr nativeHandle = Marshal.AllocHGlobal(numberOfBytes);
LocalAllocHandle safeHandle = new LocalAllocHandle();
safeHandle.SetHandle(nativeHandle);
return safeHandle;
}
}
public class DisposableBaseWithSafeHandle : IDisposable
{
// Detect redundant Dispose() calls.
private bool _isDisposed;
// Managed disposable objects owned by this class
private LocalAllocHandle? _safeHandle = LocalAllocHandle.Allocate(10);
private Stream? _otherUnmanagedResource = new MemoryStream();
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
_isDisposed = true;
if (disposing)
{
// Dispose managed state.
_otherUnmanagedResource?.Dispose();
_safeHandle?.Dispose();
_otherUnmanagedResource = null;
_safeHandle = null;
}
}
}
}
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports Microsoft.Win32.SafeHandles
' Wraps the IntPtr allocated by Marshal.AllocHGlobal() into a SafeHandle.
Public Class LocalAllocHandle
Inherits SafeHandleZeroOrMinusOneIsInvalid
Private Sub New()
MyBase.New(True)
End Sub
' No need to implement a finalizer - SafeHandle's finalizer will call ReleaseHandle for you.
Protected Overrides Function ReleaseHandle() As Boolean
Marshal.FreeHGlobal(handle)
Return True
End Function
' Allocate bytes with Marshal.AllocHGlobal() and wrap the result into a SafeHandle.
Public Shared Function Allocate(numberOfBytes As Integer) As LocalAllocHandle
Dim nativeHandle As IntPtr = Marshal.AllocHGlobal(numberOfBytes)
Dim safeHandle As New LocalAllocHandle()
safeHandle.SetHandle(nativeHandle)
Return safeHandle
End Function
End Class
Public Class DisposableBaseWithSafeHandle
Implements IDisposable
' Detect redundant Dispose() calls.
Private _isDisposed As Boolean
' Managed disposable objects owned by this class
Private _safeHandle As LocalAllocHandle = LocalAllocHandle.Allocate(10)
Private _otherUnmanagedResource As Stream = New MemoryStream()
' Public implementation of Dispose pattern callable by consumers.
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
' Protected implementation of Dispose pattern.
Protected Overridable Sub Dispose(disposing As Boolean)
If Not _isDisposed Then
_isDisposed = True
If disposing Then
' Dispose managed state.
_otherUnmanagedResource?.Dispose()
_safeHandle?.Dispose()
_otherUnmanagedResource = Nothing
_safeHandle = Nothing
End If
End If
End Sub
End Class
Poznámka
Chování třídy DisposableBaseWithSafeHandle
odpovídá chování třídy DisposableBaseWithFinalizer
v předchozím příkladu, ale přístup, který je zde ukázaný, je bezpečnější:
- Není nutné implementovat finalizátor, protože SafeHandle se postará o finalizaci.
- Není nutné synchronizovat, aby se zajistilo zabezpečení vláken. I když v
Dispose
implementaciDisposableBaseWithSafeHandle
existuje podmínka závodu, SafeHandle zaručuje, že SafeHandle.ReleaseHandle bude volána pouze jednou.
Integrované bezpečnostní popisovače v .NET
Následující odvozené třídy v oboru názvů Microsoft.Win32.SafeHandles poskytují bezpečné popisovače.
Třída | Prostředky, které obsahuje |
---|---|
SafeFileHandle SafeMemoryMappedFileHandle SafePipeHandle |
Soubory, soubory mapované v paměti a kanály |
SafeMemoryMappedViewHandle | Zobrazení paměti |
SafeNCryptKeyHandle SafeNCryptProviderHandle SafeNCryptSecretHandle |
Kryptografické konstrukce |
SafeRegistryHandle | Klíče registru |
SafeWaitHandle | Obslužné rutiny čekání |