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