private static unsafe void CreateAndStartRunLoop()
        {
            Debug.Assert(s_dynamicStoreRef == null);

            var storeContext = new Interop.SystemConfiguration.SCDynamicStoreContext();

            using (SafeCreateHandle storeName = Interop.CoreFoundation.CFStringCreateWithCString("NetworkAddressChange.OSX"))
            {
                s_dynamicStoreRef = Interop.SystemConfiguration.SCDynamicStoreCreate(
                    storeName.DangerousGetHandle(),
                    s_storeCallback,
                    &storeContext);
            }

            // Notification key string parts. We want to match notification keys
            // for any kind of IP address change, addition, or removal.
            using (SafeCreateHandle dynamicStoreDomainStateString = Interop.CoreFoundation.CFStringCreateWithCString("State:"))
                using (SafeCreateHandle compAnyRegexString = Interop.CoreFoundation.CFStringCreateWithCString("[^/]+"))
                    using (SafeCreateHandle entNetIpv4String = Interop.CoreFoundation.CFStringCreateWithCString("IPv4"))
                        using (SafeCreateHandle entNetIpv6String = Interop.CoreFoundation.CFStringCreateWithCString("IPv6"))
                        {
                            if (dynamicStoreDomainStateString.IsInvalid || compAnyRegexString.IsInvalid ||
                                entNetIpv4String.IsInvalid || entNetIpv6String.IsInvalid)
                            {
                                s_dynamicStoreRef.Dispose();
                                s_dynamicStoreRef = null;
                                throw new NetworkInformationException(SR.net_PInvokeError);
                            }

                            using (SafeCreateHandle ipv4Pattern = Interop.SystemConfiguration.SCDynamicStoreKeyCreateNetworkServiceEntity(
                                       dynamicStoreDomainStateString.DangerousGetHandle(),
                                       compAnyRegexString.DangerousGetHandle(),
                                       entNetIpv4String.DangerousGetHandle()))
                                using (SafeCreateHandle ipv6Pattern = Interop.SystemConfiguration.SCDynamicStoreKeyCreateNetworkServiceEntity(
                                           dynamicStoreDomainStateString.DangerousGetHandle(),
                                           compAnyRegexString.DangerousGetHandle(),
                                           entNetIpv6String.DangerousGetHandle()))
                                    using (SafeCreateHandle patterns = Interop.CoreFoundation.CFArrayCreate(
                                               new CFStringRef[2]
                                    {
                                        ipv4Pattern.DangerousGetHandle(),
                                        ipv6Pattern.DangerousGetHandle()
                                    }, (UIntPtr)2))
                                    {
                                        // Try to register our pattern strings with the dynamic store instance.
                                        if (patterns.IsInvalid || !Interop.SystemConfiguration.SCDynamicStoreSetNotificationKeys(
                                                s_dynamicStoreRef.DangerousGetHandle(),
                                                IntPtr.Zero,
                                                patterns.DangerousGetHandle()))
                                        {
                                            s_dynamicStoreRef.Dispose();
                                            s_dynamicStoreRef = null;
                                            throw new NetworkInformationException(SR.net_PInvokeError);
                                        }

                                        // Create a "RunLoopSource" that can be added to our listener thread's RunLoop.
                                        s_runLoopSource = Interop.SystemConfiguration.SCDynamicStoreCreateRunLoopSource(
                                            s_dynamicStoreRef.DangerousGetHandle(),
                                            IntPtr.Zero);
                                    }
                        }
            s_runLoopThread = new Thread(RunLoopThreadStart);
            s_runLoopThread.Start();
            s_runLoopStartedEvent.WaitOne(); // Wait for the new thread to finish initialization.
        }
        private static unsafe void CreateAndStartRunLoop()
        {
            Debug.Assert(s_dynamicStoreRef == null);

            var storeContext = new Interop.SystemConfiguration.SCDynamicStoreContext();
            using (SafeCreateHandle storeName = Interop.CoreFoundation.CFStringCreateWithCString("NetworkAddressChange.OSX"))
            {
                s_dynamicStoreRef = Interop.SystemConfiguration.SCDynamicStoreCreate(
                    storeName.DangerousGetHandle(),
                    s_storeCallback,
                    &storeContext);
            }

            // Notification key string parts. We want to match notification keys
            // for any kind of IP address change, addition, or removal.
            using (SafeCreateHandle dynamicStoreDomainStateString = Interop.CoreFoundation.CFStringCreateWithCString("State:"))
            using (SafeCreateHandle compAnyRegexString = Interop.CoreFoundation.CFStringCreateWithCString("[^/]+"))
            using (SafeCreateHandle entNetIpv4String = Interop.CoreFoundation.CFStringCreateWithCString("IPv4"))
            using (SafeCreateHandle entNetIpv6String = Interop.CoreFoundation.CFStringCreateWithCString("IPv6"))
            {
                if (dynamicStoreDomainStateString.IsInvalid || compAnyRegexString.IsInvalid
                    || entNetIpv4String.IsInvalid || entNetIpv6String.IsInvalid)
                {
                    s_dynamicStoreRef.Dispose();
                    s_dynamicStoreRef = null;
                    throw new NetworkInformationException(SR.net_PInvokeError);
                }

                using (SafeCreateHandle ipv4Pattern = Interop.SystemConfiguration.SCDynamicStoreKeyCreateNetworkServiceEntity(
                        dynamicStoreDomainStateString.DangerousGetHandle(),
                        compAnyRegexString.DangerousGetHandle(),
                        entNetIpv4String.DangerousGetHandle()))
                using (SafeCreateHandle ipv6Pattern = Interop.SystemConfiguration.SCDynamicStoreKeyCreateNetworkServiceEntity(
                        dynamicStoreDomainStateString.DangerousGetHandle(),
                        compAnyRegexString.DangerousGetHandle(),
                        entNetIpv6String.DangerousGetHandle()))
                using (SafeCreateHandle patterns = Interop.CoreFoundation.CFArrayCreate(
                        new CFStringRef[2]
                        {
                            ipv4Pattern.DangerousGetHandle(),
                            ipv6Pattern.DangerousGetHandle()
                        }, 2))
                {
                    // Try to register our pattern strings with the dynamic store instance.
                    if (patterns.IsInvalid || !Interop.SystemConfiguration.SCDynamicStoreSetNotificationKeys(
                                                s_dynamicStoreRef.DangerousGetHandle(),
                                                IntPtr.Zero,
                                                patterns.DangerousGetHandle()))
                    {
                        s_dynamicStoreRef.Dispose();
                        s_dynamicStoreRef = null;
                        throw new NetworkInformationException(SR.net_PInvokeError);
                    }

                    // Create a "RunLoopSource" that can be added to our listener thread's RunLoop.
                    s_runLoopSource = Interop.SystemConfiguration.SCDynamicStoreCreateRunLoopSource(
                        s_dynamicStoreRef.DangerousGetHandle(),
                        IntPtr.Zero);
                }
            }
            s_runLoopThread = new Thread(RunLoopThreadStart);
            s_runLoopThread.Start();
            s_runLoopStartedEvent.WaitOne(); // Wait for the new thread to finish initialization.
        }