private static void NotificationListenerProc() { int eventIndex = 0; while (!m_killThread) { // have to have a timeout or this thread never dies, even when the calling app is stopped eventIndex = EventWaitHandle.WaitAny(DeviceManagementInternals.m_events, 1000, true); switch (eventIndex) { case TIME_CHANGE_INDEX: m_currentEvent = TimeChanged; break; case TIMEZONE_CHANGE_INDEX: m_currentEvent = TimeZoneChanged; break; case PCCARD_CHANGE_INDEX: m_currentEvent = PCCardChanged; break; case IR_DISCOVERED_INDEX: m_currentEvent = IRDiscovered; break; case NET_CONNECT_INDEX: m_currentEvent = NetworkConnected; break; case NET_DISCONNECT_INDEX: m_currentEvent = NetworkDisconnected; break; case AC_APPLIED_INDEX: m_currentEvent = ACPowerApplied; break; case AC_REMOVED_INDEX: m_currentEvent = ACPowerRemoved; break; case RESTORE_INDEX: m_currentEvent = DeviceRestoreComplete; break; case SERIAL_DETECT_INDEX: m_currentEvent = SerialDeviceDetected; break; case SYNC_COMPLETE_INDEX: m_currentEvent = SynchronizationComplete; break; case WAKE_INDEX: m_currentEvent = DeviceWake; break; case NAME_CHANGE_INDEX: m_currentEvent = DeviceNameChange; break; case RNDIS_INDEX: m_currentEvent = RNDISDeviceDetected; break; case PROXY_CHANGE_INDEX: m_currentEvent = InternetProxyChange; break; default: // most likely a timeout m_currentEvent = null; break; } if (m_currentEvent != null) { try { m_invoker.Invoke(new EventHandler(NotificationMarshaler)); } catch (Exception) { // failure here is catastropic, so just exit the thread return; } } } }
private unsafe void ThreadProc() { IntPtr notifyHandle = NativeMethods.FindFirstChangeNotification(m_path, true, filter); FileNotifyInformation notifyData = new FileNotifyInformation(); uint returned = 0; uint available = 0; EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.ManualReset, WaitHandleName); EventWaitHandle quitWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, WaitHandleNameQuit); while (!m_quit) { ewh.Reset(); if (EventWaitHandle.WaitAny(new IntPtr[] { notifyHandle, ewh.Handle }, TimeoutInfinite, false) != EventWaitHandle.WaitTimeout) { if (m_quit) { break; } IntPtr ptr = IntPtr.Zero; if (NativeMethods.CeGetFileNotificationInfo(notifyHandle, 0, ref ptr, 0, ref returned, ref available)) { if (available > 0) { int maxData = 2048; fixed(byte *pData = new byte[maxData]) { // get data if (NativeMethods.CeGetFileNotificationInfo(notifyHandle, 0, pData, maxData, ref returned, ref available)) { notifyData = new FileNotifyInformation(pData, 0); // handle data in notifyData if (ValidateByFilter(notifyData.Filename)) { RaiseEvents(notifyData.Action, notifyData.Filename); } int offset = 0; offset += notifyData.NextEntryOffset; while (notifyData.NextEntryOffset > 0) { notifyData = new FileNotifyInformation(pData, offset); if (ValidateByFilter(notifyData.Filename)) { RaiseEvents(notifyData.Action, notifyData.Filename); } offset += notifyData.NextEntryOffset; } } } } else { //Seems that subdirectories don't return anything but then the notifyHandle is never reset and if available data is 0 notifyHandle never resets NativeMethods.FindCloseChangeNotification(notifyHandle); notifyHandle = NativeMethods.FindFirstChangeNotification(m_path, true, filter); } } } // if( waithandle... } // while (!m_quit) NativeMethods.FindCloseChangeNotification(notifyHandle); quitWaitHandle.Set(); }