1

在此处输入图像描述
如果特定 xml 文件发生更改,我想刷新我的 datagridview。我有一个 FileSystemWatcher 来查找文件中的任何更改并调用 datagirdview 函数来重新加载 xml 数据。

当我尝试时,我得到了Invalid data Exception error有人请告诉我我在这里做错了什么?

  public Form1()
            {
                InitializeComponent();
                FileSystemWatcher watcher = new FileSystemWatcher();

                watcher.Path = @"C:\test";
                watcher.Changed +=  fileSystemWatcher1_Changed;
                watcher.EnableRaisingEvents = true;
                //watches only Person.xml
                watcher.Filter = "Person.xml";

                //watches all files with a .xml extension
                watcher.Filter = "*.xml";

            }

            private const string filePath = @"C:\test\Person.xml";
            private void LoadDatagrid()
            {
                try
                {
                    using (XmlReader xmlFile = XmlReader.Create(filePath, new XmlReaderSettings()))
                    {
                        DataSet ds = new DataSet();
                        ds.ReadXml(xmlFile);
                        dataGridView1.DataSource = ds.Tables[0]; //Here is the problem
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                } 
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                LoadDatagrid();
            }

private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
            {
                LoadDatagrid();
            }
4

2 回答 2

2

这是因为在FileSystemWatcher不同的线程上运行,而不是 UI 线程。在 winforms 应用程序上,只有 UI 线程(程序的主线程)可以与视觉控件交互。如果您需要与来自另一个线程的可视控件进行交互(例如这种情况),Invoke则必须调用目标控件。

 // this event will be fired from the thread where FileSystemWatcher is running.
 private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
 {
      // Call Invoke on the current form, so the LoadDataGrid method
      // will be executed on the main UI thread.
      this.Invoke(new Action(()=> LoadDatagrid()));
 }
于 2012-08-11T14:00:54.673 回答
1

FileSystemWatcher 在单独的线程中运行,而不是在 UI 线程中。为了维护线程安全,.NET 阻止您从非 UI 线程(即创建表单组件的线程)更新 UI。

要轻松解决问题,请从您的 fileSystemWatcher1_Changed 事件中调用目标 Form 的 MethodInvoker 方法。有关如何执行此操作的更多详细信息,请参阅MethodInvoker Delegate 。关于如何执行此操作还有其他选项,包括。设置一个同步(即线程安全)对象来保存任何事件的结果/标志,但这不需要更改表单代码(即在游戏的情况下,可以只在主游戏循环中轮询同步对象等)。

private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
{
    // Invoke an anonymous method on the thread of the form.
    this.Invoke((MethodInvoker) delegate
    {
        this.LoadDataGrid();
    });
}

编辑:更正了之前在委托中有问题的答案,LoadDataGrid 缺少这个。它不会这样解决。

于 2012-08-11T13:58:26.417 回答