将文本分配给TextField时出现InvalidOperationException

时间:2010-06-25 17:46:07

标签: c# wpf

我对C#有一个奇怪的问题,我还不能解释。我实际上计划创建一个简单的文件查看器,一旦文件发生变化就会自动更新显示的文本,但事实证明它比我想象的要复杂得多。

我有以下基本代码:

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)
    }
}

现在,在更改的处理程序中对(WPF)TextField的赋值会引发System.InvalidOperationException异常,告诉我该对象已在另一个线程中使用。那么为什么我会得到这个例外,更重要的是,我需要做些什么来使这个工作?

修改

顺便说一下,无论我指定的字符串是什么,我都会得到异常。

EDIT2

例外的全文,但是用德语:

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:

1 个答案:

答案 0 :(得分:6)

FileSystemWatcher正在另一个线程上引发此事件。您不能从与创建它的线程不同的线程访问用户界面元素。

您需要使用Dispatcher推送将文本设置回UI线程的调用:

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...
        }));
}