没有调用的C#事件

时间:2011-11-18 16:28:22

标签: c# winforms events

我是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)吗?

5 个答案:

答案 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消息泵,并始终在同一个线程中运行,或者将调用编组到另一个线程上。