Reputation: 81
From what I can see in the source code for WaitHandle
in both
src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs
src/runtime/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs
namely:
public virtual void Close() => Dispose();
protected virtual void Dispose(bool explicitDisposing)
{
_waitHandle?.Close();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
It seems calling Close()
will call Dispose()
which will call Dispose(bool)
which will call Close()
...
second verse, same as the first for calling Dispose()
.
So how does this not result in an infinite loop?
Especially since none of these methods do anything which would make the _waitHandle
be null
, as far as I can understand.
Upvotes: 0
Views: 50
Reputation: 164
This is not causing infinite recursion, because similarly named method Close ()
is called on different classes. The code you are quoting is from WaitHandle
class. The private field in it has a different type:
private SafeWaitHandle? _waitHandle;
If you keep digging, SafeHandle
(which is the parent of SafeWaitHandle
) has the field and an abstract method:
// https://github.com/dotnet/runtime/blob/1d1bf92fcf43aa6981804dc53c5174445069c9e4/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeHandle.cs
protected IntPtr handle;
protected abstract bool ReleaseHandle();
ReleaseHandle()
is overridden in a partial .cs
file and resolves to WinAPI native call CloseHandle (handle)
:
// https://github.com/microsoft/referencesource/blob/master/mscorlib/microsoft/win32/safehandles/safewaithandle.cs
override protected bool ReleaseHandle()
{
return Win32Native.CloseHandle(handle);
}
The main takeaway is that System.Threading
classes are thin wrappers around underylying WinAPI system objects. Everything will have to eventually resolve to a WinAPI call.
See also: Dispose
pattern by Microsoft.
Upvotes: 3