/// <summary> /// Internally creates and starts the monitor thread. /// </summary> /// <returns> /// True if the thread was successfully created. /// To ensure the monitor was successfully activated, handle the MonitorOpened event. /// </returns> /// <remarks></remarks> protected bool internalWatch() { int blen = 0; int bufflen = (int)_Buff.Size; var tbuff = _Buff.Handle; if (_thread is object) { return(false); } if (!internalOpenFile()) { return(false); } FILE_NOTIFY_INFORMATION fn; fn.ptr = _Buff; _thread = new System.Threading.Thread(() => { var notice = IntPtr.Zero; User32.PostMessage(Handle, FileSystemMonitor.WM_SIGNAL_OPEN, IntPtr.Zero, IntPtr.Zero); do { try { // let's clean up the memory before the next execute. if (blen > 0) { _Buff.ZeroMemory(0L, blen); blen = 0; } if (!FileSystemMonitor.ReadDirectoryChangesW(_hFile, tbuff, bufflen, true, _Filter, ref blen, IntPtr.Zero, IntPtr.Zero)) { notice = (IntPtr)User32.GetLastError(); break; } } catch (System.Threading.ThreadAbortException) { break; } catch (Exception) { notice = (IntPtr)1; break; } // block until the lock is acquired. Hopefully the // UI thread will not take that long to clean the list. System.Threading.Monitor.Enter(_WaitList); _WaitList.Add(FSMonitorEventArgs.FromPtr(fn, this)); // and we're done ... System.Threading.Monitor.Exit(_WaitList); // post to the UI thread that there are items to dequeue and continue! User32.PostMessage(Handle, FileSystemMonitor.WM_SIGNAL, IntPtr.Zero, IntPtr.Zero); }while (true); _thread = null; User32.PostMessage(Handle, FileSystemMonitor.WM_SIGNAL_CLOSE, IntPtr.Zero, IntPtr.Zero); }); _thread.SetApartmentState(System.Threading.ApartmentState.STA); _thread.IsBackground = true; _thread.Start(); return(true); }