internal static extern void FSEventStreamUnscheduleFromRunLoop( SafeEventStreamHandle streamRef, CFRunLoopRef runLoop, SafeCreateHandle runLoopMode);
/// <summary> /// Creates a new EventStream to listen to events from the core OS (such as File System events). /// </summary> /// <param name="cb">A callback instance that will be called for every event batch.</param> /// <param name="pathsToWatch">A CFArray of the path(s) to watch for events.</param> /// <param name="sinceWhen"> /// The start point to receive events from. This can be to retrieve historical events or only new events. /// To get historical events, pass in the corresponding ID of the event you want to start from. /// To get only new events, pass in kFSEventStreamEventIdSinceNow. /// </param> /// <param name="latency">Coalescing period to wait before sending events.</param> /// <param name="flags">Flags to say what kind of events should be sent through this stream.</param> /// <returns>On success, returns a valid SafeCreateHandle to an FSEventStream object; otherwise, returns an invalid SafeCreateHandle</returns> internal static SafeEventStreamHandle FSEventStreamCreate( FSEventStreamCallback cb, SafeCreateHandle pathsToWatch, FSEventStreamEventId sinceWhen, CFTimeInterval latency, FSEventStreamCreateFlags flags) { return FSEventStreamCreate(IntPtr.Zero, cb, IntPtr.Zero, pathsToWatch, sinceWhen, latency, flags); }
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. }
private static extern SafeEventStreamHandle FSEventStreamCreate( IntPtr allocator, FSEventStreamCallback cb, IntPtr context, SafeCreateHandle pathsToWatch, FSEventStreamEventId sinceWhen, CFTimeInterval latency, FSEventStreamCreateFlags flags);
private static void RunLoopThreadStart() { Debug.Assert(s_runLoop == IntPtr.Zero); s_runLoop = Interop.RunLoop.CFRunLoopGetCurrent(); Interop.RunLoop.CFRunLoopAddSource( s_runLoop, s_runLoopSource.DangerousGetHandle(), Interop.RunLoop.kCFRunLoopDefaultMode.DangerousGetHandle()); s_runLoopStartedEvent.Set(); Interop.RunLoop.CFRunLoopRun(); Interop.RunLoop.CFRunLoopRemoveSource( s_runLoop, s_runLoopSource.DangerousGetHandle(), Interop.RunLoop.kCFRunLoopDefaultMode.DangerousGetHandle()); s_runLoop = IntPtr.Zero; s_runLoopSource.Dispose(); s_runLoopSource = null; s_dynamicStoreRef.Dispose(); s_dynamicStoreRef = null; s_runLoopEndedEvent.Set(); }