Search code examples
c#richtextboxfilesystemwatcher

How do I keep a RichTextBox updated constantly with a TXT file?


I have this code, which should keep richTextBox2 updated at all times with usedPath's contents, but it doesn't.

 private void watch()
    {
        var usedPath = Path.Combine(Directory.GetCurrentDirectory(), "usedwords.txt");

        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = usedPath;
        watcher.NotifyFilter = NotifyFilters.LastWrite;
        watcher.Filter = "*.txt*";
        watcher.Changed += new FileSystemEventHandler(OnChanged);
        watcher.EnableRaisingEvents = true;
    }

    private void OnChanged(object source, FileSystemEventArgs e)
    {
        string usedPath = Path.Combine(Directory.GetCurrentDirectory(), "usedwords.txt");
        richTextBox2.LoadFile(usedPath, RichTextBoxStreamType.PlainText);
    }

Can someone help me figure out what I have wrong?


Solution

  • Problem 1: Your watcher.Path = path of a single file, which will cause error.

    Solution: Look at this: Use FileSystemWatcher on a single file in C#

    watcher.Path = Path.GetDirectoryName(filePath1); 
    watcher.Filter = Path.GetFileName(filePath1);
    

    Problem 2: Accessing richTextBox2 in OnChanged() will cause cross-thread error

    Solution: Use this:

    private void OnChanged(object source, FileSystemEventArgs e)
    {
        Invoke((MethodInvoker)delegate
        {
              string usedPath = Path.Combine(Directory.GetCurrentDirectory(), "usedwords.txt");
              richTextBox2.LoadFile(usedPath, RichTextBoxStreamType.PlainText);      
        });
    }
    

    Problem 3: There may be error when trying to LoadFile while some other programs are writing to it.

    (Possible) Solution: Put a Thread.Sleep(10) in before trying to LoadFile in OnChanged

        private void OnChanged(object source, FileSystemEventArgs e)
        {
            Thread.Sleep(10);
            Invoke((MethodInvoker)delegate
            {
                richTextBox1.LoadFile(usedPath, RichTextBoxStreamType.PlainText);
            });
        }
    

    My complete code:

    public partial class Form1 : Form
    {
        string usedPath = @"C:\Users\xxx\Desktop\usedwords.txt";
    
        public Form1()
        {
            InitializeComponent();
            watch();
        }
    
        private void watch()
        {
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = Path.GetDirectoryName(usedPath);
            watcher.Filter = Path.GetFileName(usedPath);
            watcher.NotifyFilter = NotifyFilters.LastWrite;
            watcher.Changed += new FileSystemEventHandler(OnChanged);
            watcher.EnableRaisingEvents = true;
        }
    
        private void OnChanged(object source, FileSystemEventArgs e)
        {
            Thread.Sleep(10);
            Invoke((MethodInvoker)delegate
            {
                richTextBox1.LoadFile(usedPath, RichTextBoxStreamType.PlainText);
            });
        }
    }