FileSystemWatcher无效数据异常错误

时间:2012-08-11 13:03:22

标签: c# xml winforms filesystemwatcher

enter image description here
如果特定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();
            }

2 个答案:

答案 0 :(得分: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()));
 }

答案 1 :(得分:1)

FileSystemWatcher在单独的线程中运行,而不是在UI线程中运行。为了保持线程安全,.NET阻止您从非UI线程(即创建Form组件的线程)更新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错过了这个。并且它不会这样解决。