我是C#Event的新手,我想在不收到跨线程错误的情况下触发事件..
using System;
using System.Timers;
public class SampleTickEvent
{
private string passStr = string.Empty;
Timer t = new Timer(1000);
public delegate void ImageEventHandler(string s);
public event ImageEventHandler ImageEventTrigger;
public void Start(string ss)
{
passStr = ss;
t.Start();
t.Elapsed += t_Elapsed;
}
public void t_Elapsed(object sender, ElapsedEventArgs eea)
{
ImageEventTrigger(passStr);
}
}
private void button1_Click(object sender, EventArgs e)
{
SampleTickEvent ste = new SampleTickEvent();
ste.Start("sample");
ste.ImageEventTrigger += ste_ImageEventTrigger;
}
private void ste_ImageEventTrigger(string s)
{
Action act = () => listBox1.Items.Add(s);
Invoke(act);
}
还有另一种方法,我不会把Action act =()= ...并放入listbox1.Items.Add(s)吗?
答案 0 :(得分:3)
而不是使用System.Timers.Timer
,尝试使用System.Windows.Forms.Timer
,这是为了在UI线程上引发事件而编写的。
答案 1 :(得分:2)
如果您使用的是Windows窗体,则可以使用System.Windows.Forms.Timer而不是System.Timers.Timer。 tick事件在UI线程中执行:http://netpl.blogspot.com/2010/05/systemwindowsformstimer-vs.html
答案 2 :(得分:1)
不,Timer
对线程池中的线程进行操作,因此为了安全地修改表单控件,您需要使用Invoke
。
你可以内联动作,但就是这样。
如果您想将Invoke
放入SampleTickEvent.t_Elapsed
方法,那么您必须首先将Control
作为句柄传递到SampleTickEvent
。或者,您可以在其构造函数中创建一个新的Control
作为SampleTickEvent
的成员,并在其上调用Invoke
。我之前就这样做过。
答案 3 :(得分:1)
您可以在应用程序启动期间更改此选项:
System.Windows.Forms.Form.CheckForIllegalCrossThreadCalls = false;
这将用于您使用的Form
作为主应用程序线程。
答案 4 :(得分:1)
尝试使用System.Windows.Forms.Timer
代替System.Timers.Timer
。
从上面的Msdn Link:
此Windows计时器专为使用UI线程执行处理的单线程环境而设计。它要求用户代码具有可用的UI消息泵,并始终在同一个线程中运行,或者将调用编组到另一个线程上。