0

I am getting list of my files in a directory and print their names on console, meanwhile i am adding a new file to the directory(Directory is monitored by FileSystemWatcher) to print its name, But it throws an exception: Collection was modified; Enumeration operation may not be executed..

This is the code:

private static void Main(string[] args)
    {
        var myfiles = new List<string>();
        myfiles = Directory.GetFiles(@"c:\items").ToList();

        foreach (var file in myfiles)
        {
            Console.WriteLine(file);
        }
    }

    public static void Run(List<string> myfiles)
    {
        var watcher = new FileSystemWatcher { Path = @"c:\items" };
        watcher.Created += (source, e) =>
        {
            myfiles.Add(e.FullPath);
        };
        watcher.EnableRaisingEvents = true;
    }

Q: How can i add item to list using Watcher while i am iterating through the list? is there any other way to add item to list in RealTime while iterating?

Note: In debugging i saw the Watcher will add the item to list properly, But after the item was added it throws an Exception.

Note: I also created a 2nd thread and put the Watcher in it.

1 Answers1

0

The main issue here is that you're adding to your myFiles list (albeit on a separate thread) whilst trying to iterate the list in your `foreach (var file in myfiles)'. You cannot add items to a List whilst iterating over it.

Have a look at the built-in BlockingCollection, it allows you to implement a Producer/Consumer pattern which is ideal for these kind of scenarios.

Here is a working example:

class Program
    {
        private static string _directoryName = @"c:\items";

        private static readonly BlockingCollection<string> FilesList = new BlockingCollection<string>();

        static void Main(string[] args)
        {
            Run();

            var myfiles = Directory.GetFiles(_directoryName).ToList();

            foreach (var file in myfiles)
            {
                FilesList.Add(file);
            }

            foreach (var item in FilesList.GetConsumingEnumerable())
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }

        public static void Run()
        {
            var watcher = new FileSystemWatcher { Path = _directoryName };
            watcher.Created += (source, e) =>
            {
                FilesList.Add(e.FullPath);
            };
            watcher.EnableRaisingEvents = true;
        }
    }
Janus Pienaar
  • 1,083
  • 7
  • 14
  • What would you like the end result to be? I'm assuming you want to (1) List ALL files in the folder when the Console app starts app. (2) Show new files in Console as they get added to the folder? – Janus Pienaar Oct 31 '17 at 12:47
  • That's not what the error is about. YOu'd get the *same* error if you tried to modify the list from inside the loop, in the same thread. In fact, the FSW does *not* use a separate thread – Panagiotis Kanavos Oct 31 '17 at 12:47
  • Agree, it doesn't matter which Thread tries to add to the List, the point is, you can't add to a list whilst iterating over it. – Janus Pienaar Oct 31 '17 at 12:48
  • Then you have to change this answer because it says the opposite. You *won't* fix this by adding a BlockingCollection. There are no threads to block here – Panagiotis Kanavos Oct 31 '17 at 12:48
  • @JanusPienaar This is Exactly what i want. – dewina thrice Oct 31 '17 at 12:49
  • @dewinathrice it's not, because you don't have *threads*. The problem was caused by `foreach`. You could use a Queue and call `Dequeue` to get items without iterating – Panagiotis Kanavos Oct 31 '17 at 12:50
  • @PanagiotisKanavos Ok i got the idea, let me try it. – dewina thrice Oct 31 '17 at 12:52
  • @dewinathrice I've added a working example using the BlockingCollection – Janus Pienaar Oct 31 '17 at 13:06
  • @PanagiotisKanavos Changed `foreach (var file in myfiles)` to `foreach (var file in myfiles.ToList())` and the Exception fixed, but it will not show the added items. – dewina thrice Oct 31 '17 at 13:12