@@ -390,7 +390,10 @@ private void CreateSubdirectoryWatchers(DirectorySnapshot snapshot)
390390 // Share parent's cancellation token so entire tree can be cancelled together
391391 var childWatcher = new RunningInstance ( watcher , subdirPath , subdirRelativePath , true , _notifyFilters , _cancellationToken ) ;
392392 childWatcher . Start ( ) ;
393- _subdirectoryWatchers . Add ( childWatcher ) ;
393+ lock ( _subdirectoryWatchers )
394+ {
395+ _subdirectoryWatchers . Add ( childWatcher ) ;
396+ }
394397 subdirCount ++ ;
395398 }
396399 }
@@ -756,10 +759,17 @@ private void ProcessDeletion(FileSystemWatcher watcher, string name, FileEntry o
756759 if ( isDir && _includeSubdirectories )
757760 {
758761 string subdirPath = System . IO . Path . Combine ( _directoryPath , name ) ;
759- var childToRemove = _subdirectoryWatchers . Find ( c => c . _directoryPath == subdirPath ) ;
762+ RunningInstance ? childToRemove ;
763+ lock ( _subdirectoryWatchers )
764+ {
765+ childToRemove = _subdirectoryWatchers . Find ( c => c . _directoryPath == subdirPath ) ;
766+ if ( childToRemove is not null )
767+ {
768+ _subdirectoryWatchers . Remove ( childToRemove ) ;
769+ }
770+ }
760771 if ( childToRemove is not null )
761772 {
762- _subdirectoryWatchers . Remove ( childToRemove ) ;
763773 childToRemove . Cancel ( ) ;
764774 }
765775 }
@@ -787,10 +797,17 @@ private void ProcessRename(FileSystemWatcher watcher, string oldName, FileEntry
787797 if ( isDir && _includeSubdirectories )
788798 {
789799 string oldSubdirPath = System . IO . Path . Combine ( _directoryPath , oldName ) ;
790- var childToUpdate = _subdirectoryWatchers . Find ( c => c . _directoryPath == oldSubdirPath ) ;
800+ RunningInstance ? childToUpdate ;
801+ lock ( _subdirectoryWatchers )
802+ {
803+ childToUpdate = _subdirectoryWatchers . Find ( c => c . _directoryPath == oldSubdirPath ) ;
804+ if ( childToUpdate is not null )
805+ {
806+ _subdirectoryWatchers . Remove ( childToUpdate ) ;
807+ }
808+ }
791809 if ( childToUpdate is not null )
792810 {
793- _subdirectoryWatchers . Remove ( childToUpdate ) ;
794811 childToUpdate . Cancel ( ) ;
795812 CreateSingleSubdirectoryWatcher ( newName ) ;
796813 }
@@ -833,7 +850,10 @@ private void CreateSingleSubdirectoryWatcher(string name)
833850 {
834851 var childWatcher = new RunningInstance ( watcher , subdirPath , subdirRelativePath , true , _notifyFilters , _cancellationToken ) ;
835852 childWatcher . Start ( ) ;
836- _subdirectoryWatchers . Add ( childWatcher ) ;
853+ lock ( _subdirectoryWatchers )
854+ {
855+ _subdirectoryWatchers . Add ( childWatcher ) ;
856+ }
837857 }
838858 }
839859 catch ( Exception ex )
@@ -980,9 +1000,13 @@ internal void Cancel()
9801000 _isCancelling = true ;
9811001
9821002 // First, cancel all subdirectory watchers (depth-first)
983- // ToArray() creates a snapshot to avoid race conditions with ProcessEvents thread
984- // modifying the list during iteration
985- foreach ( var child in _subdirectoryWatchers . ToArray ( ) )
1003+ // Take a lock when creating the snapshot to avoid races with concurrent modifications
1004+ RunningInstance [ ] children ;
1005+ lock ( _subdirectoryWatchers )
1006+ {
1007+ children = _subdirectoryWatchers . ToArray ( ) ;
1008+ }
1009+ foreach ( RunningInstance child in children )
9861010 {
9871011 child . Cancel ( ) ;
9881012 }
0 commit comments