从filesystemeventhandler访问Form1元素

时间:2012-02-07 02:41:24

标签: c# multithreading forms events filesystemwatcher

我有一个程序正在检查文件中的更改,然后一旦文件发生更改就会读取它并更新一些标签。 “但是它崩溃了,因为我试图从一个不同的线程中改变一个线程中的元素”〜或者我认为。有什么想法吗?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.IO;
using System.Threading.Tasks;


namespace RoomAutomation
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void readfile_Click(object sender, EventArgs e)
        {

            string[] lines = System.IO.File.ReadAllLines(@"C:\Users\Dandrews\control.txt");
            FileSystemWatcher fsw = new FileSystemWatcher();
            fsw.Path = @"C:\Users\Dandrews\";
            fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite |
                            NotifyFilters.DirectoryName | NotifyFilters.FileName;
            fsw.Changed += new FileSystemEventHandler(OnChanged); 
            fsw.EnableRaisingEvents = true;
            if (lines[0] == "1:lights")
            {
                Lights.Text = "Lights are on.";
            }
            if (lines[0] == "0:lights")
            {
                Lights.Text = "Lights are off.";
            }
            if (lines[1] == "1:camera")
            {
            Camera.Text = "Camera is on.";
            }
            if (lines[1] == "0:camera")
            {
                Camera.Text = "Camera is off.";
            }
            if (lines[2] == "1:speakers")
            {
                Speakers.Text = "Speakers are on.";
            }
            if (lines[2] == "0:speakers")
            {
                Speakers.Text = "Speakers are off.";
            }
            if (lines[3] == "1:playlist")
            {
                Playlist.Text = "Playlist is on.";
            }
            if (lines[3] == "0:playlist")
            {
                Playlist.Text = "Playlist is off.";
            }        
        }
        private void OnChanged(object source, FileSystemEventArgs e)
        {            
            Console.Write("Changes");
            //Lights.Text = "New label Text";

        }
    }
}

`

2 个答案:

答案 0 :(得分:1)

那是因为FileSystemWatcher在线程池线程上引发了它的事件。这是自然的方式,那些文件系统事件是异步发生的。您不能直接访问事件处理程序中的任何UI组件,它们不是线程安全的。 InvalidOperationException用于提醒您不能。

修复它需要添加一行代码:

        fsw.SynchronizingObject = this;

强制FileSystemWatcher将事件处理程序调用封送到创建表单的线程UI线程。这不一定是最好的解决方案,编组调用涉及大量开销。但是对于这个解决方案你会很好,因为你 为每个事件编组,无论如何都使用你现在的代码。

答案 1 :(得分:0)

.NET 2.0及以上版本doesn't allow you to access UI elements from other threads。您必须调用调用要在控件上运行的代码。如果您正在移植.NET 1.1代码,那么这将是一个简单的黑客攻击:

http://codebetter.com/jeremymiller/2006/11/06/using-anonymous-methods-with-control-invoke/