internal static void Stop(NetworkAddressChangedEventHandler?caller)
 {
     if (caller != null)
     {
         lock (s_globalLock)
         {
             s_addressChangedSubscribers.Remove(caller);
             if (s_addressChangedSubscribers.Count == 0 && s_isListening)
             {
                 s_isListening = false;
             }
         }
     }
 }
            private static void StartHelper(NetworkAddressChangedEventHandler?caller, bool captureContext, StartIPOptions startIPOptions)
            {
                lock (s_globalLock)
                {
                    // Setup changedEvent and native overlapped struct.
                    if (s_ipv4Socket == null)
                    {
                        // Sockets will be initialized by the call to OSSupportsIP*.
                        if (Socket.OSSupportsIPv4)
                        {
                            s_ipv4Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0)
                            {
                                Blocking = false
                            };
                            s_ipv4WaitHandle = new AutoResetEvent(false);
                        }

                        if (Socket.OSSupportsIPv6)
                        {
                            s_ipv6Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, 0)
                            {
                                Blocking = false
                            };
                            s_ipv6WaitHandle = new AutoResetEvent(false);
                        }
                    }

                    if (caller != null)
                    {
                        s_addressChangedSubscribers.TryAdd(caller, captureContext ? ExecutionContext.Capture() : null);
                    }

                    if (s_isListening || s_addressChangedSubscribers.Count == 0)
                    {
                        return;
                    }

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

                            SocketError errorCode = Interop.Winsock.WSAIoctl_Blocking(
                                s_ipv4Socket !.SafeHandle,
                                (int)IOControlCode.AddressListChange,
                                null, 0, null, 0,
                                out int length,
                                IntPtr.Zero, IntPtr.Zero);

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

                            errorCode = Interop.Winsock.WSAEventSelect(
                                s_ipv4Socket.SafeHandle,
                                s_ipv4WaitHandle !.GetSafeWaitHandle(),
                                Interop.Winsock.AsyncEventBits.FdAddressListChange);

                            if (errorCode != SocketError.Success)
                            {
                                throw new NetworkInformationException();
                            }
                        }

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

                            SocketError errorCode = Interop.Winsock.WSAIoctl_Blocking(
                                s_ipv6Socket !.SafeHandle,
                                (int)IOControlCode.AddressListChange,
                                null, 0, null, 0,
                                out int length,
                                IntPtr.Zero, IntPtr.Zero);

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

                            errorCode = Interop.Winsock.WSAEventSelect(
                                s_ipv6Socket.SafeHandle,
                                s_ipv6WaitHandle !.GetSafeWaitHandle(),
                                Interop.Winsock.AsyncEventBits.FdAddressListChange);

                            if (errorCode != SocketError.Success)
                            {
                                throw new NetworkInformationException();
                            }
                        }
                    }

                    s_isListening = true;
                    s_isPending   = true;
                }
            }
 internal static void UnsafeStart(NetworkAddressChangedEventHandler?caller)
 {
     StartHelper(caller, false, StartIPOptions.Both);
 }