System.IO.FileSystemWatcher.Monitor C# (CSharp) Method

Monitor() private method

Initiates the next asynchronous read operation if monitoring is still desired. If the directory handle has been closed due to an error or due to event monitoring being disabled, this cleans up state associated with the operation.
private Monitor ( AsyncReadState state ) : void
state AsyncReadState
return void
        private unsafe void Monitor(AsyncReadState state)
        {
            // This method should only ever access the directory handle via the state object passed in, and not access it
            // via _directoryHandle.  While this function is executing asynchronously, another thread could set 
            // EnableRaisingEvents to false and then back to true, restarting the FSW and causing a new directory handle 
            // and thread pool binding to be stored.  This function could then get into an inconsistent state by doing some 
            // operations against the old handles and some against the new.

            NativeOverlapped* overlappedPointer = null;
            bool continueExecuting = false;
            try
            {
                // If shutdown has been requested, exit.  The finally block will handle
                // cleaning up the entire operation, as continueExecuting will remain false.
                if (!_enabled || IsHandleInvalid(state.DirectoryHandle))
                    return;

                // Get the overlapped pointer to use for this iteration.
                overlappedPointer = state.ThreadPoolBinding.AllocateNativeOverlapped(state.PreAllocatedOverlapped);
                int size;
                continueExecuting = Interop.Kernel32.ReadDirectoryChangesW(
                    state.DirectoryHandle,
                    state.Buffer, // the buffer is kept pinned for the duration of the sync and async operation by the PreAllocatedOverlapped
                    _internalBufferSize,
                    _includeSubdirectories,
                    (int)_notifyFilters,
                    out size,
                    overlappedPointer,
                    IntPtr.Zero);
            }
            catch (ObjectDisposedException)
            {
                // Ignore.  Disposing of the handle is the mechanism by which the FSW communicates
                // to the asynchronous operation to stop processing.
            }
            catch (ArgumentNullException)
            {
                //Ignore.  The disposed handle could also manifest as an ArgumentNullException.
                Debug.Assert(IsHandleInvalid(state.DirectoryHandle), "ArgumentNullException from something other than SafeHandle?");
            }
            finally
            {
                // At this point the operation has either been initiated and we'll let the callback
                // handle things from here, or the operation has been stopped or failed, in which case
                // we need to cleanup because we're no longer executing.
                if (!continueExecuting)
                {
                    // Clean up the overlapped pointer created for this iteration
                    if (overlappedPointer != null)
                    {
                        state.ThreadPoolBinding.FreeNativeOverlapped(overlappedPointer);
                    }

                    // Clean up the thread pool binding created for the entire operation
                    state.PreAllocatedOverlapped.Dispose();
                    state.ThreadPoolBinding.Dispose();

                    // Finally, if the handle was for some reason changed or closed during this call, 
                    // then don't throw an exception.  Otherwise, it's a valid error.
                    if (!IsHandleInvalid(state.DirectoryHandle))
                    {
                        OnError(new ErrorEventArgs(new Win32Exception()));
                    }
                }
            }
        }