protected void ProtectedInvokeCallback(object result, IntPtr userToken)
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(this, result, userToken);
// Critical to disallow DBNull here - it could result in a stuck spinlock in WaitForCompletion.
if (result == DBNull.Value)
{
throw new ArgumentNullException(nameof(result));
}
#if DEBUG
// Always safe to ask for the state now.
_protectState = false;
#endif
if ((_intCompleted & ~HighBit) == 0 && (Interlocked.Increment(ref _intCompleted) & ~HighBit) == 1)
{
// DBNull.Value is used to guarantee that the first caller wins,
// even if the result was set to null.
if (_result == DBNull.Value)
{
_result = result;
}
ManualResetEvent asyncEvent = (ManualResetEvent)_event;
if (asyncEvent != null)
{
try
{
asyncEvent.Set();
}
catch (ObjectDisposedException)
{
// Simply ignore this exception - There is apparently a rare race condition
// where the event is disposed before the completion method is called.
}
}
Complete(userToken);
}
}