System.Net.LazyAsyncResult.WaitForCompletion C# (CSharp) Method

WaitForCompletion() private method

private WaitForCompletion ( bool snap ) : object
snap bool
return object
        private object WaitForCompletion(bool snap)
        {
            ManualResetEvent waitHandle = null;
            bool createdByMe = false;
            bool complete = snap ? IsCompleted : InternalPeekCompleted;

            if (!complete)
            {
                // Not done yet, so wait:
                waitHandle = (ManualResetEvent)_event;
                if (waitHandle == null)
                {
                    createdByMe = LazilyCreateEvent(out waitHandle);
                }
            }

            if (waitHandle != null)
            {
                try
                {
                    if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Waiting for completion event {waitHandle}");
                    waitHandle.WaitOne(Timeout.Infinite);
                }
                catch (ObjectDisposedException)
                {
                    // This can occur if this method is called from two different threads.
                    // This possibility is the trade-off for not locking.
                }
                finally
                {
                    // We also want to dispose the event although we can't unless we did wait on it here.
                    if (createdByMe && !_userEvent)
                    {
                        // Does _userEvent need to be volatile (or _event set via Interlocked) in order
                        // to avoid giving a user a disposed event?
                        ManualResetEvent oldEvent = (ManualResetEvent)_event;
                        _event = null;
                        if (!_userEvent)
                        {
                            oldEvent.Dispose();
                        }
                    }
                }
            }

            // A race condition exists because InvokeCallback sets _intCompleted before _result (so that _result
            // can benefit from the synchronization of _intCompleted).  That means you can get here before _result got
            // set (although rarely - once every eight hours of stress).  Handle that case with a spin-lock.

            SpinWait sw = new SpinWait();
            while (_result == DBNull.Value)
            {
                sw.SpinOnce();
            }

            if (NetEventSource.IsEnabled) NetEventSource.Exit(this, _result);
            return _result;
        }