Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

InvalidOperationException when assigning text to a TextField

Tags:

c#

wpf

I am having a weird problem with C#, I can't yet explain. I actually planned to create a simple file viewer that automatically updates the displayed text as soon as the file is changed, but it turns out more complicated than I thought.

I have the following basic code:

public partial class Main : Window
{
    private FileSystemWatcher watcher;
    private String filePath = "C:\\";
    private String fileName = "example.txt";

    public Main()
    {
        InitializeComponent();

        this.txtFile.Text = File.ReadAllText(filePath + fileName);

        this.watcher = new FileSystemWatcher(filePath);
        this.watcher.Changed += new FileSystemEventHandler(watcher_Changed);
        this.watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite;
        this.watcher.Filter = fileName;
        this.watcher.EnableRaisingEvents = true;
    }

    void watcher_Changed(object sender, FileSystemEventArgs e)
    {
        String text = File.ReadAllText(e.FullPath);
        this.txtFile.Text = text; // <-- here comes the exception (line 42)
    }
}

Now the assignment to the (WPF) TextField in the changed handler raises a System.InvalidOperationException exception, telling me that the object is already used in a different thread. So why do I get that exception and more importantly, what do I have to do, to make this working?

edit

By the way, I get the exception regardless of the string I'm assigning.

edit2

Full text of the exception, but in german:

System.InvalidOperationException wurde nicht behandelt.
  Message="Der aufrufende Thread kann nicht auf dieses Objekt zugreifen, da sich das Objekt im Besitz eines anderen Threads befindet."
  Source="WindowsBase"
  StackTrace:
       bei System.Windows.Threading.Dispatcher.VerifyAccess()
       bei System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
       bei System.Windows.Controls.TextBox.set_Text(String value)
       bei LiveTextViewer.Main.watcher_Changed(Object sender, FileSystemEventArgs e) in ...\Main.xaml.cs:Zeile 42.
       bei System.IO.FileSystemWatcher.CompletionStatusChanged(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* overlappedPointer)
       bei System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
  InnerException:
like image 751
poke Avatar asked Jun 25 '10 17:06

poke


1 Answers

FileSystemWatcher is raising this event on a different thread. You can't access user interface elements from a different thread than the one on which it was created.

You'll need to use the Dispatcher to push the call that sets the text back onto the UI thread:

void watcher_Changed(object sender, FileSystemEventArgs e)
{
    String text = File.ReadAllText(e.FullPath);

    this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => 
        {
             this.txtFile.Text = text;
             // Do all UI related work here...
        }));
}
like image 147
Reed Copsey Avatar answered Sep 19 '22 17:09

Reed Copsey