Search code examples
c#multithreadingfile-watcher

SystemFileWatcher in side multithread not working


I am trying to watch changes occurring to files in all the USB storage devices that are connected to my PC. To do that I wrote a c# console application but it is not working only giving a blank screen. please someone help me to do this

class

    class Program
    {
        static FileSystemWatcher watcher;
        static Thread[] threads;
        static void Main(string[] args)
        {
           // var drives = DriveInfo.GetDrives();
            DriveInfo[] drives = DriveInfo.GetDrives();
            for (int i = 0; i < drives.Length; i++)
            {
                var drive = drives[i];
                if (drive.DriveType == DriveType.Removable && isDirectoryEmpty(drive.Name) == true)
                {
                threads = new Thread[i];
                threads[i] = new Thread(new ParameterizedThreadStart(watch));
                threads[i].Start(drive.Name);
                }

            }
            foreach (Thread t in threads)
            {
                t.Start();
            }

        }
        static bool isDirectoryEmpty(string path)
        {
            if (!Directory.Exists(path)) return false;
            return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any();
        }
        static void watch(object pth)
        {
            string path = (string)pth;

            watcher = new FileSystemWatcher();

            watcher.Path = path;//assigning path to be watched
            watcher.EnableRaisingEvents = true;//make sure watcher will raise event in case of change in folder.
            watcher.IncludeSubdirectories = true;//make sure watcher will look into subfolders as well.
            watcher.Filter = "*.*"; //watcher should monitor all types of file.


            watcher.Created += watcher_Created;//register event to be called when a file is created in specified path
            watcher.Changed += watcher_Changed;//register event to be called when a file is updated in specified path
            watcher.Deleted += watcher_Deleted;//register event to be called when a file is deleted in specified path


            //while (true) ;
        }

        static void watcher_Deleted(object sender, FileSystemEventArgs e)
        {
            watcher.EnableRaisingEvents = true;
            Console.WriteLine("File : " + e.FullPath + " is deleted.");
            watcher.EnableRaisingEvents = true;
        }

        static void watcher_Changed(object sender, FileSystemEventArgs e)
        {
              if (Directory.Exists(e.FullPath))
                {
                    watch(e.FullPath);
                }
                else
                {
                    Console.WriteLine("File : " + e.FullPath + " is updated.");

                        try
                        {
                            if (!string.IsNullOrEmpty(e.FullPath))
                            {
                                watcher.EnableRaisingEvents = false;
                                File.Delete(e.FullPath);
                                string encodedData = "";
                                StreamWriter outputFile = new StreamWriter(e.FullPath, false);

                                    outputFile.Write(encodedData);
                                    outputFile.Flush();
                                    outputFile.Close();

                                watcher.EnableRaisingEvents = true;
                                //break;

                            }

                        }
                        catch (Exception excep)
                        {
                            Console.WriteLine(excep.Message.ToString());
                            Thread.Sleep(1000);
                        }


                }
   }

        static void watcher_Created(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File : " + e.FullPath + " is created.");




        }
}

Solution

  • The key issues I found were the console exited immediately after starting threads (hence the while not Q)

    The threads were started twice.. once with parameter, and one with just .start

    the thread array didnt work for me at all, code crashed. So I made it a list and added the new thread to it.

    I removed the "on change" processing so nothing else was messed up - after all the goal was to get a working watcher in a thread

    OK this is very simplified but this code works - I hacked at yours until it worked- the code is not production code, it is not tidy, it doesnt clean threads at the end blah blah blah.

    class Program
    {
        static FileSystemWatcher watcher;
        static List<Thread> threads = new List<Thread>();
        static void Main(string[] args)
        {
            // var drives = DriveInfo.GetDrives();
            DriveInfo[] drives = DriveInfo.GetDrives();
            for (int i = 0; i < drives.Length; i++)
            {
                var drive = drives[i];
                if (drive.DriveType == DriveType.Removable)
                {
                    Console.WriteLine("Watching drive " + drive.Name);
    
                    Thread t = new Thread(new ParameterizedThreadStart(watch));
                    t.Start(drive.Name);
    
                    threads.Add(t);
                }
    
            }
            while(Console.ReadKey().Key != ConsoleKey.Q )
                    { Thread.SpinWait(10); }
            Console.Write("done");
            Console.ReadLine();
    
        }
    
        static void watch(object pth)
        {
            string path = (string)pth;
    
            watcher = new FileSystemWatcher();
            watcher.Created += watcher_Created;//register event to be called when a file is created in specified path
            watcher.Changed += watcher_Changed;//register event to be called when a file is updated in specified path
            watcher.Deleted += watcher_Deleted;//register event to be called when a file is deleted in specified path
    
            watcher.Path = path;//assigning path to be watched
            watcher.IncludeSubdirectories = true;//make sure watcher will look into subfolders as well.
            watcher.Filter = "*.*"; //watcher should monitor all types of file.
            watcher.EnableRaisingEvents = true;//make sure watcher will raise event in case of change in folder.
    
        }
    
        static void watcher_Deleted(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File : " + e.FullPath + " is deleted.");
        }
    
        static void watcher_Changed(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File : " + e.FullPath + " is updated.");
        }
    
        static void watcher_Created(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File : " + e.FullPath + " is created.");
        }
    }
    

    Adding output as requested:

    Input: Input

    Output: Output