C# 对于我的简单挑战,线程/独立执行?
我的表单包含14个标签和一个以100ms为间隔连续运行的计时器。在计时器中有与文件系统接口并检查某个文件是否存在的代码。根据此文件的存在(简单的真或假),标签的背景颜色将从灰色更改为红色,如果不再满足条件,则将其更改为灰色 到目前为止一切正常。我可以编程,没有问题,它的工作 现在,这个表单上还有几个按钮,我可能需要随时点击。然而,有一个滞后,这使得用户体验好像表单被占用了。我猜这是因为计时器必须更新UI,因此无法完全“集中”于我的点击请求。我正在寻找一个简单的例子,它可能会帮助我掌握线程/独立执行的基本知识,或者任何术语。我很感激这里有很多例子,但你们当中有一位可爱的人能建议我在我的应用程序上下文中可能需要做什么吗C# 对于我的简单挑战,线程/独立执行?,c#,multithreading,C#,Multithreading,我的表单包含14个标签和一个以100ms为间隔连续运行的计时器。在计时器中有与文件系统接口并检查某个文件是否存在的代码。根据此文件的存在(简单的真或假),标签的背景颜色将从灰色更改为红色,如果不再满足条件,则将其更改为灰色 到目前为止一切正常。我可以编程,没有问题,它的工作 现在,这个表单上还有几个按钮,我可能需要随时点击。然而,有一个滞后,这使得用户体验好像表单被占用了。我猜这是因为计时器必须更新UI,因此无法完全“集中”于我的点击请求。我正在寻找一个简单的例子,它可能会帮助我掌握线程/独立执
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (System.IO.File.Exists("C:\file.txt") == true)
{
label1.BackColor = System.Drawing.Color.Red;
//label2.BackColour..
//label3.BackColour..
//..
}
if (System.IO.File.Exists("C:\file.txt") == false)
{
label1.BackColor = System.Drawing.Color.Gray;
//label2.BackColour..
//label3.BackColour..
//..
}
}
private void button1_Click(object sender, EventArgs e)
{
//Do something
}
}
}
使用而不是在计时器上轮询文件。David Nelson建议的FileSystemWatcher是一个更好的选择,这是一种快速且(非常)肮脏的方式:
public partial class Form1 : Form
{
private System.Threading.Timer timer1;
public Form1()
{
InitializeComponent();
this.timer1 = new System.Threading.Timer(state => {
var fileExists = System.IO.File.Exists(@"C:\file.txt");
this.BeginInvoke(new Action(() => {
if (fileExists) {
label1.BackColor = System.Drawing.Color.Red;
//label2.BackColour..
//label3.BackColour..
//..
}
else {
label1.BackColor = System.Drawing.Color.Gray;
//label2.BackColour..
//label3.BackColour..
//..
}
}));
}, null, 0, 100);
}
private void button1_Click(object sender, EventArgs e)
{
}
}
假设延迟的罪魁祸首是
File.Exists
调用,而不是多个BackColor
分配,您可以使用将代价高昂的调用卸载到线程池线程,然后等待
以获得结果:
private async void Timer1_Tick(object sender, EventArgs e)
{
var fileExists = await Task.Run(() => File.Exists("C:\file.txt"));
Color color = fileExists ? Color.Red : Color.Gray;
label1.BackColor = color;
label2.BackColor = color;
label3.BackColor = color;
//...
}
问题到底是什么?@svick我猜这更像是一个设计问题。Nathan你准备好迎接挑战了吗,新技术?+1是的,这正是要做的-当检测到文件时,按一下按钮找出要更改的颜色。无延迟、CPU浪费、GUI冻结轮询。System.Threading.Timer将调用线程池线程上的委托,这意味着您将访问非UI线程上的控件,这将引发异常。我尝试在针对.NET FW 4的WinForms项目的VS11中运行此代码,结果成功。我知道它会抛出异常,但事实并非如此。碰巧,背景色可以从背景线程设置而不会失败;然而,这是一个随时可能改变的实现细节。从后台线程设置WinForms控件的任何属性都可能失败。