Inheritance: System.MarshalByRefObject
Example #1
0
		public void SetTimer(int MillisecondTimeout, TimeElapsedHandler CB)
		{
			lock(TimeoutList)
			{
				long Ticks = DateTime.Now.AddMilliseconds(MillisecondTimeout).Ticks;
				while(TimeoutList.ContainsKey(Ticks)==true)
				{
					++Ticks;
				}

				TimeoutList.Add(Ticks,CB);
				if(TimeoutList.Count==1)
				{
					// First Entry
					mre.Reset();
					handle = ThreadPool.RegisterWaitForSingleObject(
						mre,
						WOTcb,
						null,
						MillisecondTimeout,
						true);
				}
				else
				{
					mre.Set();
				}
			}
		}
        public HeartbeatSender(TimeSpan period, RestTarget heartbeatRest)
        {
            _period = period;
            _heartbeatRest = heartbeatRest;

            _registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(_disposeEvent, SendHeartBeats, null, _period, false);
        }
Example #3
0
        public bool unregister()
        {
            ManualResetEvent callbackThreadComplete = new ManualResetEvent(false);
            int timeToWait = 5000; //milliseconds
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            if (this.sessionRegisteredWait != null)
            {
                if (this.sessionRegisteredWait.Unregister(callbackThreadComplete))
                {
                    Console.WriteLine("waiting on succesful unregister");
                    callbackThreadComplete.WaitOne(timeToWait);
                }
            }
            this.sessionRegisteredWait = null;

            long elapsed = sw.ElapsedMilliseconds;
            Console.WriteLine("Elapsed: {0} millisec", elapsed);
            if (elapsed >= timeToWait)
            {
                Console.WriteLine("Error. Callback was not signaled");
                return false;
            }
            else
            {
                Console.WriteLine("Success");
                return true;
            }
            

            

        }
Example #4
0
 public CallbackInfo(Action<RawBusMessage, Exception> callback, Type replyType, ManualResetEvent ev, RegisteredWaitHandle handle)
 {
     _callback = callback;
     _replyType = replyType;
     _ev = ev;
     _handle = handle;
 }
Example #5
0
        /// <summary>
        /// create a buffer recorder for a stream
        /// </summary>
        /// <param name="number">ordinal for diagnostics</param>
        /// <param name="streamID">the stream I'm for</param>
        public BufferRecorder( int number, int streamID )
        {
            isAvailable = true;

            this.number =  number;

            indices = new Index[Constants.IndexCapacity];
            currentIndex = 0;

            buffer = new byte[Constants.BufferSize];
            this.streamID = streamID;

            // setup the db writer thread
            canSave = new AutoResetEvent(false);
            // The BufferTimeout feature is "turned off" so that the buffer won't automatically write to disk sporadically.
            //  This is a nice safety feature we should try to turn back on.  It was turned off because it was saving data
            //  and causing frames to be written out of order in the DB.
            waitHandle = ThreadPool.RegisterWaitForSingleObject( canSave,
                new WaitOrTimerCallback(InitiateSave),
                this,
                Constants.BufferTimeout,
                false);

            Thread.Sleep(50); // Allows for the Registration to occur & get setup
            // Without the Sleep, if we walk into a massive session with lots of data moving, we get slammed & can't keep up.
        }
Example #6
0
        /// <summary>
        /// set ourselves up, we are pretty dumb so need to be told who we're sending for
        /// and where to get our data from, and when to start sending..
        /// </summary>
        /// <remarks>
        /// It seems that we don't use maxFrameSize any more.  hmm.  Remove it?
        /// </remarks>
        public BufferPlayer(int streamID, int maxFrameSize, int maxFrameCount, int maxBufferSize)
        {
            Debug.Assert( maxBufferSize >= maxFrameSize ); // just for kicks...

            buffer = new BufferChunk( maxBufferSize );
            indices = new Index[maxFrameCount+1]; // Pri3: why is this "+1" here? (DO NOT REMOVE YET)

            this.populating = false;
            this.streamOutOfData = false;
            this.streamID = streamID;

            this.currentIndex = 0;
            this.indexCount = 0;
            this.startingTick = 0;

            canPopulate = new AutoResetEvent(false);

            // pool a thread to re-populate ourselves
            waitHandle = ThreadPool.RegisterWaitForSingleObject(
                canPopulate,
                new WaitOrTimerCallback( InitiatePopulation ),
                this,
                -1, // never timeout to perform a population
                false );
        }
Example #7
0
 private void BeginRunOnTimer(object state, bool isTimeout)
 {
     //Wait for this race condition to satisfy
     while (m_registeredHandle == null)
         ;
     m_registeredHandle.Unregister(null);
     m_registeredHandle = null;
     OnRunning();
 }
Example #8
0
        private volatile int flushIsRunning = 0; // 0 = false, 1 = true

        #endregion Fields

        #region Constructors

        public QueueLogWriter()
        {
            File.Delete(aof);

            fileStream = new FileStream(aof, FileMode.OpenOrCreate, FileAccess.Write);

            flushSignalWaitHandle
                = ThreadPool.RegisterWaitForSingleObject(flushSignal, (state, timedOut) => Flush(), null, -1, false);
            flushSignal.Set(); // signal to start pump right away
        }
Example #9
0
 public EventsQueue(Boolean bufferedOutput, Int32 autoFlushPeriod, 
     Action<IEnumerable<EventRecord>> flushAction)
 {
     this.bufferedOutput = bufferedOutput;
     this.flushAction = flushAction;
     this.syncObject = new Object();
     this.eventsList = new List<EventRecord>();
     this.flushEvent = new AutoResetEvent(false);
     this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(
         this.flushEvent, FlushEventSignaledCallback, null, autoFlushPeriod * 1000, false);
 }
 public unsafe void CancelAsyncOperation()
 {
     this.rootedHolder.ThisHolder = null;
     if (this.registration != null)
     {
         this.registration.Unregister(null);
         this.registration = null;
     }
     this.bufferPtr = null;
     this.bufferHolder[0] = dummyBuffer;
     this.pendingCallback = null;
 }
Example #11
0
 private static void InitializeConnectionTimeoutHandler()
 {
     _socketTimeoutDelegate = new WaitOrTimerCallback(TimeoutConnections);
     _socketTimeoutWaitHandle = new AutoResetEvent(false);
     _registeredWaitHandle = 
         ThreadPool.UnsafeRegisterWaitForSingleObject(
             _socketTimeoutWaitHandle, 
             _socketTimeoutDelegate, 
             "IpcConnectionTimeout", 
             _socketTimeoutPollTime, 
             true); // execute only once
 } // InitializeSocketTimeoutHandler
        public void RegisterTimeout(TimeSpan interval, Action callback)
        {
            lock (m_syncRoot)
            {
                if (m_callback != null)
                    throw new Exception("Duplicate calls are not permitted");

                m_callback = callback;
                m_resetEvent = new ManualResetEvent(false);
                m_registeredHandle = ThreadPool.RegisterWaitForSingleObject(m_resetEvent, BeginRun, null, interval, true);
            }
        }
Example #13
0
 static Log() {
   _useDiagnostic = System.Diagnostics.Debugger.IsAttached;
   try { int window_height = Console.WindowHeight; _useConsole = true; }
   catch { _useConsole = false; }
   if(!Directory.Exists("../log")) {
     Directory.CreateDirectory("../log");
   }
   useFile = true;
   _lfMask = "../log/{0}_" + Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location) + ".log";
   _records = new System.Collections.Concurrent.ConcurrentQueue<LogRecord>();
   _kickEv = new AutoResetEvent(false);
   _wh = ThreadPool.RegisterWaitForSingleObject(_kickEv, Process, null, -1, false);
 }
 private static void TimeoutSockets(object state, bool wasSignalled)
 {
     DateTime utcNow = DateTime.UtcNow;
     lock (_connections)
     {
         foreach (DictionaryEntry entry in _connections)
         {
             ((RemoteConnection) entry.Value).TimeoutSockets(utcNow);
         }
     }
     _registeredWaitHandle.Unregister(null);
     _registeredWaitHandle = ThreadPool.UnsafeRegisterWaitForSingleObject(_socketTimeoutWaitHandle, _socketTimeoutDelegate, "TcpChannelSocketTimeout", _socketTimeoutPollTime, true);
 }
 private void BeginRun(object state, bool isTimeout)
 {
     lock (m_syncRoot)
     {
         if (m_registeredHandle == null)
             return;
         m_registeredHandle.Unregister(null);
         m_resetEvent.Dispose();
         m_callback();
         m_resetEvent = null;
         m_registeredHandle = null;
         m_callback = null;
     }
 }
 public void Cancel()
 {
     lock (m_syncRoot)
     {
         if (m_registeredHandle != null)
         {
             m_registeredHandle.Unregister(null);
             m_resetEvent.Dispose();
             m_resetEvent = null;
             m_registeredHandle = null;
             m_callback = null;
         }
     }
 }
Example #17
0
        public void register()
        {


            this.sessionNotification = new ManualResetEvent(false);
      
            this.sessionRegisteredWait = ThreadPool.RegisterWaitForSingleObject(
                                                            this.sessionNotification,
                                                            ServiceCallbackOnPositionAvailable,
                                                            this,   /* object state */
                                                            -1,     /* INFINITE */
                                                            true    /* ExecuteOnlyOnce */);


        }
        private void Begin(Func<AsyncCallback, object, IAsyncResult> beginMethod, AsyncCallback callback, object state, TimeSpan timeout)
        {
            this.asyncResult = beginMethod(callback, state);

#if WINDOWS_PHONE
            WaitHandle asyncWaitHandle = this.fakeEvent;
#else
            WaitHandle asyncWaitHandle = this.asyncResult.AsyncWaitHandle;
#endif

            this.waitHandle = ThreadPool.RegisterWaitForSingleObject(asyncWaitHandle, this.WaitCallback, state, timeout, true);
            if (this.disposed)
            {
                this.UnregisterWaitHandle();
            }
        }
Example #19
0
        public ConnectionCache(int keepAlive, ConnectionFactory connectionFactory)
        {
            // parameters validation
            if (connectionFactory == null)
                throw new ArgumentNullException("connectionFactory");
            if (keepAlive < 1)
                throw new ArgumentOutOfRangeException("keepAlive");

            _connectionFactory = connectionFactory;
            _keepAlive = TimeSpan.FromSeconds(keepAlive);

            // Schedule timeout method
            _timeoutDelegate = OnTimerElapsed;
            _timeoutWaitHandle = new AutoResetEvent(false);
            _registeredTimeoutWaitHandle = ThreadPool.RegisterWaitForSingleObject(
                _timeoutWaitHandle, _timeoutDelegate, null, _keepAlive, true);
        }
Example #20
0
        public void ServiceCallbackOnPositionAvailable(Object state, bool timedOut)
        {

            if (this.sessionRegisteredWait == null)
            {
                this.sessionNotification.Reset();
                this.sessionRegisteredWait.Unregister(null);

                this.sessionRegisteredWait =
                        ThreadPool.RegisterWaitForSingleObject(this.sessionNotification,
                                                                ServiceCallbackOnPositionAvailable,
                                                                this,   /* object state */
                                                                -1,     /* INFINITE */
                                                                true    /* ExecuteOnlyOnce */);

            }
            Console.WriteLine("callback running");

        }
Example #21
0
        } // InitializeSocketTimeoutHandler

        private static void TimeoutConnections(Object state, Boolean wasSignalled)
        {
            DateTime currentTime = DateTime.UtcNow;

            lock (_connections)
            {
                foreach (DictionaryEntry entry in _connections)
                {
                    PortConnection connection = (PortConnection)entry.Value; 
                    if (DateTime.Now - connection.LastUsed > _portLifetime)
                        connection.Port.Dispose();
                }
            }
            
            _registeredWaitHandle.Unregister(null);
            _registeredWaitHandle =
                ThreadPool.UnsafeRegisterWaitForSingleObject(
                    _socketTimeoutWaitHandle, 
                    _socketTimeoutDelegate, 
                    "IpcConnectionTimeout", 
                    _socketTimeoutPollTime, 
                    true); // execute only once      
        } // TimeoutConnections
Example #22
0
        /// <summary>
        /// create a buffer manager for a stream
        /// </summary>
        /// <param name="number">ordinal for diagnostics</param>
        /// <param name="streamID">the stream I'm for</param>
        public BufferManager( int number, int streamID )
        {
            isAvailable = true;

            this.number =  number;

            indices = new Index[Constants.IndexCapacity];
            currentIndex = 0;

            buffer = new byte[Constants.BufferSize];
            this.streamID = streamID;

            // setup the db writer thread
            canSave = new AutoResetEvent(false);
            waitHandle = ThreadPool.RegisterWaitForSingleObject( canSave,
                new WaitOrTimerCallback(InitiateSave),
                this,
                Constants.BufferTimeout,
                false);

            Thread.Sleep(50); // Allows for the Registration to occur & get setup
            // Without the Sleep, if we walk into a massive session with lots of data moving, we get slammed & can't keep up.
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="nextCheckSeconds">check again after X seconds</param>
        /// <param name="containerName">what container to sync</param>
        public static void CheckAsync(int nextCheckSeconds, string containerName, string rootPath)
        {
            lock (typeof(QuickDeployService)) {
                
                // clear existing handle if already exists
                if (RegisteredWaitHandle != null)
                    RegisteredWaitHandle.Unregister(null);

                var waitHandle = new AutoResetEvent(false);
                RegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(
                    waitHandle,
                    // Method to execute
                    (state, timeout) => {
                        WhenTimeComes(containerName, rootPath);
                    },
                    // optional state object to pass to the method
                    null,
                    // Execute the method after 5 seconds
                    TimeSpan.FromSeconds(nextCheckSeconds),
                    // Set this to false to execute it repeatedly every 5 seconds
                    false
                );
            }
        }
        private static void AddNameChanged(EventHandler<NameChangedEventArgs> callback)
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddNameChanged().");

            //
            // Register a wait handle if one has not been registered already
            //
            lock (LockNameChangedEvent)
            {
                if (s_nameChanged == null){
                    s_nameChangedEvent = new AutoResetEvent(false);

                    //
                    // Register callback with a wait handle
                    //

                    s_regNameChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(s_nameChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(NameChangedCallback), //callback to be called 
                                            null, //state to be passed
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set
                                            );
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();

                    pcer.eventType = PeerCollabEventType.MyEndPointChanged;
                    pcer.pInstance = IntPtr.Zero;

                    //
                    // Register event with collab
                    //

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                s_nameChangedEvent.SafeWaitHandle,
                                                                1,
                                                                ref pcer,
                                                                out s_safeNameChangedEvent);
                    if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_NameChangedRegFailed), errorCode);
                    }
                }
                s_nameChanged += callback;
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddNameChanged() successful.");
        }
 // We need this to make the use of the property as an attribute 
 // light-weight. This allows us to delay initialize everything we
 // need to fully function as a ContextProperty.
 internal virtual void InitIfNecessary()
 {
     lock(this) 
     {
         if (_asyncWorkEvent == null)
         {
             // initialize thread pool event to non-signaled state.
             _asyncWorkEvent = new AutoResetEvent(false);
 
             _workItemQueue = new Queue();
             _asyncLcidList = new ArrayList();
             
             WaitOrTimerCallback callBackDelegate = 
                 new WaitOrTimerCallback(this.DispatcherCallBack);
 
             // Register a callback to be executed by the thread-pool
             // each time the event is signaled.
             _waitHandle = ThreadPool.RegisterWaitForSingleObject(
                             _asyncWorkEvent, 
                             callBackDelegate, 
                             null, // state info
                             _timeOut, 
                             false); // bExecuteOnlyOnce
         }
     }
 }
        private void HandleTimer(Object State, bool TimedOut)
        {
            ArrayList TriggerList = new ArrayList();
            lock (TimeoutList)
            {
                while (TimeoutList.Count > 0)
                {
                    DateTime timeout = new DateTime((long)TimeoutList.GetKey(0));
                    TimeElapsedHandler cb = (TimeElapsedHandler)TimeoutList.GetByIndex(0);

                    if (DateTime.Now.CompareTo(timeout) >= 0)
                    {
                        // Trigger
                        TriggerList.Add(cb);
                        TimeoutList.RemoveAt(0);
                    }
                    else
                    {
                        // Reset timer
                        mre.Reset();
                        int MillisecondTimeout = (int)new TimeSpan(timeout.Ticks - DateTime.Now.Ticks).TotalMilliseconds;
                        if (MillisecondTimeout <= 0)
                        {
                            mre.Set();
                            MillisecondTimeout = 0;
                        }
                        handle = ThreadPool.RegisterWaitForSingleObject(mre, WOTcb, null, MillisecondTimeout, true);
                        break;
                    }
                }
            }
            foreach (TimeElapsedHandler _cb in TriggerList)
            {
                _cb(this);
            }
        }
        internal void StartSubscribing() {

            if (this.isSubscribing)
                throw new InvalidOperationException();

            int flag = 0;
            if (bookmark != null)
                flag |= (int)UnsafeNativeMethods.EvtSubscribeFlags.EvtSubscribeStartAfterBookmark;
            else if (this.readExistingEvents)
                flag |= (int)UnsafeNativeMethods.EvtSubscribeFlags.EvtSubscribeStartAtOldestRecord;
            else
                flag |= (int)UnsafeNativeMethods.EvtSubscribeFlags.EvtSubscribeToFutureEvents;

            if (this.eventQuery.TolerateQueryErrors)
                flag |= (int)UnsafeNativeMethods.EvtSubscribeFlags.EvtSubscribeTolerateQueryErrors;

            EventLogPermissionHolder.GetEventLogPermission().Demand();

            this.callbackThreadId = -1;
            this.unregisterDoneHandle = new AutoResetEvent(false);
            this.subscriptionWaitHandle = new AutoResetEvent(false);

            EventLogHandle bookmarkHandle = EventLogRecord.GetBookmarkHandleFromBookmark(bookmark);

            using (bookmarkHandle) {

                handle = NativeWrapper.EvtSubscribe(this.eventQuery.Session.Handle,
                    this.subscriptionWaitHandle.SafeWaitHandle,
                    this.eventQuery.Path,
                    this.eventQuery.Query,
                    bookmarkHandle,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    flag);
            }

            this.isSubscribing = true;

            RequestEvents();

            this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(
                this.subscriptionWaitHandle,
                new WaitOrTimerCallback(SubscribedEventsAvailableCallback),
                null,
                -1,
                false);          
        }
        internal void StopSubscribing() {

            EventLogPermissionHolder.GetEventLogPermission().Demand();

            //
            // need to set isSubscribing to false before waiting for completion of callback.
            // 
            this.isSubscribing = false;

            if (this.registeredWaitHandle != null) {

                this.registeredWaitHandle.Unregister( this.unregisterDoneHandle );

                if (this.callbackThreadId != Thread.CurrentThread.ManagedThreadId) {
                    //
                    // not calling Stop from within callback - wait for 
                    // any outstanding callbacks to complete.
                    // 
                    if ( this.unregisterDoneHandle != null )
                        this.unregisterDoneHandle.WaitOne();
                }
   
                this.registeredWaitHandle = null;
            }

            if (this.unregisterDoneHandle != null) {
                this.unregisterDoneHandle.Close();
                this.unregisterDoneHandle = null;
            }

            if (this.subscriptionWaitHandle != null) {
                this.subscriptionWaitHandle.Close();
                this.subscriptionWaitHandle = null;
            }

            for (int i = 0; i < this.numEventsInBuffer; i++) {

                if (eventsBuffer[i] != IntPtr.Zero) {
                    NativeWrapper.EvtClose(eventsBuffer[i]);
                    eventsBuffer[i] = IntPtr.Zero;
                }
            }

            this.numEventsInBuffer = 0;
            
            if (handle != null && !handle.IsInvalid)
                handle.Dispose();
        }
Example #29
0
        } // InitializeSocketTimeoutHandler

        private void TimeoutSockets(Object state, Boolean wasSignalled)
        {
            DateTime currentTime = DateTime.Now;

            lock (_connections)
            {
                foreach (DictionaryEntry entry in _connections)
                {
                    RemoteConnection connection = (RemoteConnection)entry.Value; 
                    connection.TimeoutSockets(currentTime);
                }
            }
            
            _registeredWaitHandle.Unregister(null);
            _registeredWaitHandle =
                ThreadPool.UnsafeRegisterWaitForSingleObject(
                    _socketTimeoutWaitHandle, 
                    _socketTimeoutDelegate, 
                    "TcpChannelSocketTimeout", 
                    _socketTimeoutPollTime, 
                    true); // execute only once      
        } // TimeoutSockets
 public CompletedWaitHandle(RegisteredWaitHandle completedHandle, bool timedOut)
 {
     CompletedHandle = completedHandle;
     TimedOut        = timedOut;
 }
            /// <summary>
            /// The main routine for the wait thread.
            /// </summary>
            private void WaitThreadStart()
            {
                while (true)
                {
                    ProcessRemovals();
                    int numUserWaits = _numUserWaits;
                    int preWaitTimeMs = Environment.TickCount;

                    // Recalculate Timeout
                    int timeoutDurationMs = Timeout.Infinite;
                    if (numUserWaits == 0)
                    {
                        timeoutDurationMs = ThreadPoolThreadTimeoutMs;
                    }
                    else
                    {
                        for (int i = 0; i < numUserWaits; i++)
                        {
                            if (_registeredWaits[i].IsInfiniteTimeout)
                            {
                                continue;
                            }

                            int handleTimeoutDurationMs = _registeredWaits[i].TimeoutTimeMs - preWaitTimeMs;

                            if (timeoutDurationMs == Timeout.Infinite)
                            {
                                timeoutDurationMs = handleTimeoutDurationMs > 0 ? handleTimeoutDurationMs : 0;
                            }
                            else
                            {
                                timeoutDurationMs = Math.Min(handleTimeoutDurationMs > 0 ? handleTimeoutDurationMs : 0, timeoutDurationMs);
                            }

                            if (timeoutDurationMs == 0)
                            {
                                break;
                            }
                        }
                    }

                    int signaledHandleIndex = WaitHandle.WaitAny(new ReadOnlySpan<WaitHandle>(_waitHandles, 0, numUserWaits + 1), timeoutDurationMs);

                    if (signaledHandleIndex == 0) // If we were woken up for a change in our handles, continue.
                    {
                        continue;
                    }

                    RegisteredWaitHandle signaledHandle = signaledHandleIndex != WaitHandle.WaitTimeout ? _registeredWaits[signaledHandleIndex - 1] : null;

                    if (signaledHandle != null)
                    {
                        QueueWaitCompletion(signaledHandle, false);
                    }
                    else
                    {
                        if(numUserWaits == 0)
                        {
                            if (ThreadPoolInstance.TryRemoveWaitThread(this))
                            {
                                return;
                            }
                        }

                        int elapsedDurationMs = Environment.TickCount - preWaitTimeMs; // Calculate using relative time to ensure we don't have issues with overflow wraparound
                        for (int i = 0; i < numUserWaits; i++)
                        {
                            RegisteredWaitHandle registeredHandle = _registeredWaits[i];
                            int handleTimeoutDurationMs = registeredHandle.TimeoutTimeMs - preWaitTimeMs;
                            if (elapsedDurationMs >= handleTimeoutDurationMs)
                            {
                                QueueWaitCompletion(registeredHandle, true);
                            }
                        }
                    }
                }
            }
 public CompleteWaitThreadPoolWorkItem(RegisteredWaitHandle registeredWaitHandle, bool timedOut)
 {
     _registeredWaitHandle = registeredWaitHandle;
     _timedOut             = timedOut;
 }
            /// <summary>
            /// The main routine for the wait thread.
            /// </summary>
            private void WaitThreadStart()
            {
                while (true)
                {
                    // This value is taken inside the lock after processing removals. In this iteration these are the number of
                    // user waits that will be waited upon. Any new waits will wake the wait and the next iteration would
                    // consider them.
                    int numUserWaits = ProcessRemovals();

                    int currentTimeMs = Environment.TickCount;

                    // Recalculate Timeout
                    int timeoutDurationMs = Timeout.Infinite;
                    if (numUserWaits == 0)
                    {
                        timeoutDurationMs = ThreadPoolThreadTimeoutMs;
                    }
                    else
                    {
                        for (int i = 0; i < numUserWaits; i++)
                        {
                            RegisteredWaitHandle registeredWait = _registeredWaits[i];
                            Debug.Assert(registeredWait != null);
                            if (registeredWait.IsInfiniteTimeout)
                            {
                                continue;
                            }

                            int handleTimeoutDurationMs = Math.Max(0, registeredWait.TimeoutTimeMs - currentTimeMs);

                            if (timeoutDurationMs == Timeout.Infinite)
                            {
                                timeoutDurationMs = handleTimeoutDurationMs;
                            }
                            else
                            {
                                timeoutDurationMs = Math.Min(handleTimeoutDurationMs, timeoutDurationMs);
                            }

                            if (timeoutDurationMs == 0)
                            {
                                break;
                            }
                        }
                    }

                    int signaledHandleIndex = WaitHandle.WaitAny(new ReadOnlySpan <SafeWaitHandle>(_waitHandles, 0, numUserWaits + 1), timeoutDurationMs);

                    if (signaledHandleIndex >= WaitHandle.WaitAbandoned &&
                        signaledHandleIndex < WaitHandle.WaitAbandoned + 1 + numUserWaits)
                    {
                        // For compatibility, treat an abandoned mutex wait result as a success and ignore the abandonment
                        Debug.Assert(signaledHandleIndex != WaitHandle.WaitAbandoned); // the first wait handle is an event
                        signaledHandleIndex += WaitHandle.WaitSuccess - WaitHandle.WaitAbandoned;
                    }

                    if (signaledHandleIndex == 0) // If we were woken up for a change in our handles, continue.
                    {
                        continue;
                    }

                    if (signaledHandleIndex != WaitHandle.WaitTimeout)
                    {
                        RegisteredWaitHandle signaledHandle = _registeredWaits[signaledHandleIndex - 1];
                        Debug.Assert(signaledHandle != null);
                        QueueWaitCompletion(signaledHandle, false);
                        continue;
                    }

                    if (numUserWaits == 0 && ThreadPoolInstance.TryRemoveWaitThread(this))
                    {
                        return;
                    }

                    currentTimeMs = Environment.TickCount;
                    for (int i = 0; i < numUserWaits; i++)
                    {
                        RegisteredWaitHandle registeredHandle = _registeredWaits[i];
                        Debug.Assert(registeredHandle != null);
                        if (!registeredHandle.IsInfiniteTimeout && currentTimeMs - registeredHandle.TimeoutTimeMs >= 0)
                        {
                            QueueWaitCompletion(registeredHandle, true);
                        }
                    }
                }
            }
            private static void StartHelper(NetworkAddressChangedEventHandler caller, bool captureContext, StartIPOptions startIPOptions)
            {
                lock (s_callerArray) {
                    // setup changedEvent and native overlapped struct.
                    if(s_ipv4Socket == null){
                        Socket.InitializeSockets();

                        int blocking;

                        if(Socket.OSSupportsIPv4){
                            blocking = -1;
                            s_ipv4Socket = SafeCloseSocketAndEvent.CreateWSASocketWithEvent(AddressFamily.InterNetwork, SocketType.Dgram, (ProtocolType)0, true, false);
                            UnsafeNclNativeMethods.OSSOCK.ioctlsocket(s_ipv4Socket, IoctlSocketConstants.FIONBIO,ref blocking);
                            s_ipv4WaitHandle = s_ipv4Socket.GetEventHandle();
                        }

                        if(Socket.OSSupportsIPv6){
                            blocking = -1;
                            s_ipv6Socket = SafeCloseSocketAndEvent.CreateWSASocketWithEvent(AddressFamily.InterNetworkV6, SocketType.Dgram, (ProtocolType)0, true, false);
                            UnsafeNclNativeMethods.OSSOCK.ioctlsocket(s_ipv6Socket,IoctlSocketConstants.FIONBIO,ref blocking);
                            s_ipv6WaitHandle = s_ipv6Socket.GetEventHandle();
                        }
                    }

                    if ((caller != null) && (!s_callerArray.Contains(caller))) {
                        s_callerArray.Add(caller, captureContext ? ExecutionContext.Capture() : null);
                    }

                    //if s_listener is not null, it means we are already actively listening
                    if (s_isListening || s_callerArray.Count == 0) {
                        return;
                    }

                    if(!s_isPending){

                        int length;
                        SocketError errorCode;

                        if(Socket.OSSupportsIPv4 && (startIPOptions & StartIPOptions.StartIPv4) !=0){
                            s_registeredWait = ThreadPool.UnsafeRegisterWaitForSingleObject(
                                s_ipv4WaitHandle,
                                new WaitOrTimerCallback(AddressChangedCallback),
                                StartIPOptions.StartIPv4,
                                -1,
                                true );

                            errorCode = (SocketError) UnsafeNclNativeMethods.OSSOCK.WSAIoctl_Blocking(
                                s_ipv4Socket.DangerousGetHandle(),
                                (int) IOControlCode.AddressListChange,
                                null, 0, null, 0,
                                out length,
                                SafeNativeOverlapped.Zero, IntPtr.Zero);

                            if (errorCode != SocketError.Success) {
                                NetworkInformationException exception = new NetworkInformationException();
                                if (exception.ErrorCode != (uint)SocketError.WouldBlock) {
                                    throw exception;
                                }
                            }

                            errorCode = (SocketError)UnsafeNclNativeMethods.OSSOCK.WSAEventSelect(s_ipv4Socket, s_ipv4Socket.GetEventHandle().SafeWaitHandle, AsyncEventBits.FdAddressListChange);
                            if (errorCode != SocketError.Success) {
                               throw new NetworkInformationException();
                            }
                        }

                        if(Socket.OSSupportsIPv6 && (startIPOptions & StartIPOptions.StartIPv6) !=0){
                            s_registeredWait = ThreadPool.UnsafeRegisterWaitForSingleObject(
                                s_ipv6WaitHandle,
                                new WaitOrTimerCallback(AddressChangedCallback),
                                StartIPOptions.StartIPv6,
                                -1,
                                true );

                            errorCode = (SocketError) UnsafeNclNativeMethods.OSSOCK.WSAIoctl_Blocking(
                                s_ipv6Socket.DangerousGetHandle(),
                                (int) IOControlCode.AddressListChange,
                                null, 0, null, 0,
                                out length,
                                SafeNativeOverlapped.Zero, IntPtr.Zero);

                            if (errorCode != SocketError.Success) {
                                NetworkInformationException exception = new NetworkInformationException();
                                if (exception.ErrorCode != (uint)SocketError.WouldBlock) {
                                    throw exception;
                                }
                            }

                            errorCode = (SocketError)UnsafeNclNativeMethods.OSSOCK.WSAEventSelect(s_ipv6Socket, s_ipv6Socket.GetEventHandle().SafeWaitHandle, AsyncEventBits.FdAddressListChange);
                            if (errorCode != SocketError.Success) {
                               throw new NetworkInformationException();
                            }
                        }
                    }

                    s_isListening = true;
                    s_isPending = true;
                }
            }
 /// <summary>
 /// Unregisters a wait handle.
 /// </summary>
 /// <param name="handle">The handle to unregister.</param>
 /// <remarks>
 /// As per CoreCLR's behavior, if the user passes in an invalid <see cref="WaitHandle"/>
 /// into <see cref="RegisteredWaitHandle.Unregister(WaitHandle)"/>, then the unregistration of the wait handle is blocking.
 /// Otherwise, the unregistration of the wait handle is queued on the wait thread.
 /// </remarks>
 public void UnregisterWait(RegisteredWaitHandle handle)
 {
     UnregisterWait(handle, true);
 }
            /// <summary>
            /// Go through the <see cref="_pendingRemoves"/> array and remove those registered wait handles from the <see cref="_registeredWaits"/>
            /// and <see cref="_waitHandles"/> arrays, filling the holes along the way.
            /// </summary>
            private int ProcessRemovals()
            {
                PortableThreadPool threadPoolInstance = ThreadPoolInstance;

                threadPoolInstance._waitThreadLock.Acquire();
                try
                {
                    Debug.Assert(_numPendingRemoves >= 0);
                    Debug.Assert(_numPendingRemoves <= _pendingRemoves.Length);
                    Debug.Assert(_numUserWaits >= 0);
                    Debug.Assert(_numUserWaits <= _registeredWaits.Length);
                    Debug.Assert(_numPendingRemoves <= _numUserWaits, $"Num removals {_numPendingRemoves} should be less than or equal to num user waits {_numUserWaits}");

                    if (_numPendingRemoves == 0 || _numUserWaits == 0)
                    {
                        return(_numUserWaits); // return the value taken inside the lock for the caller
                    }
                    int originalNumUserWaits      = _numUserWaits;
                    int originalNumPendingRemoves = _numPendingRemoves;

                    // This is O(N^2), but max(N) = 63 and N will usually be very low
                    for (int i = 0; i < _numPendingRemoves; i++)
                    {
                        RegisteredWaitHandle waitHandleToRemove = _pendingRemoves[i] !;
                        int numUserWaits = _numUserWaits;
                        int j            = 0;
                        for (; j < numUserWaits && waitHandleToRemove != _registeredWaits[j]; j++)
                        {
                        }
                        Debug.Assert(j < numUserWaits);

                        waitHandleToRemove.OnRemoveWait();

                        if (j + 1 < numUserWaits)
                        {
                            // Not removing the last element. Due to the possibility of there being duplicate system wait
                            // objects in the wait array, perhaps even with different handle values due to the use of
                            // DuplicateHandle(), don't reorder handles for fairness. When there are duplicate system wait
                            // objects in the wait array and the wait object gets signaled, the system may release the wait in
                            // in deterministic order based on the order in the wait array. Instead, shift the array.

                            int removeAt = j;
                            int count    = numUserWaits;
                            Array.Copy(_registeredWaits, removeAt + 1, _registeredWaits, removeAt, count - (removeAt + 1));
                            _registeredWaits[count - 1] = null !;

                            // Corresponding elements in the wait handles array are shifted up by one
                            removeAt++;
                            count++;
                            Array.Copy(_waitHandles, removeAt + 1, _waitHandles, removeAt, count - (removeAt + 1));
                            _waitHandles[count - 1] = null !;
                        }
                        else
                        {
                            // Removing the last element
                            _registeredWaits[j] = null !;
                            _waitHandles[j + 1] = null !;
                        }

                        _numUserWaits      = numUserWaits - 1;
                        _pendingRemoves[i] = null;

                        waitHandleToRemove.Handle.DangerousRelease();
                    }
                    _numPendingRemoves = 0;

                    Debug.Assert(originalNumUserWaits - originalNumPendingRemoves == _numUserWaits,
                                 $"{originalNumUserWaits} - {originalNumPendingRemoves} == {_numUserWaits}");
                    return(_numUserWaits); // return the value taken inside the lock for the caller
                }
                finally
                {
                    threadPoolInstance._waitThreadLock.Release();
                }
            }