c#事件处理程序被添加两次

时间:2011-03-03 12:28:11

标签: c# event-handling timer

这是一个虚构的例子,但是我在徘徊如果InitialiseTimer函数被调用两次会发生什么。计时器已用完的功能是否被触发两次。如果函数是静态的,这会改变吗?

    private static void InitialiseTimer()
    {
            TheTimer = new System.Timers.Timer();
            TheTimer.Interval = 400;
            TheTimer.Elapsed += new ElapsedEventHandler(TheTimer_Elapsed);
            TheTimer.AutoReset = false;
    }   

    public void TheTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        //Do stuff in here
    }

我打算在下面使用以防止这个

Has an event handler already been added?

谢谢, 理查德

5 个答案:

答案 0 :(得分:5)

如果您注册事件处理程序两次,则每次引发事件时都会调用它两次。

如果你使TheTimer_Elapsed为静态,这不会改变,因为你仍然会对这个静态方法有两个引用。

在大多数情况下,没有必要像布莱尔康拉德在你所链接的问题中所写的那样编写复杂的内容。每次-=时都不要忘记使用+=,这样你就会安全。

答案 1 :(得分:4)

我认为以下内容演示了该场景并且确实发生了两次,还提出了一个简单的更改(注释代码)到应该修复行为的Init方法。 (不是线程安全btw,需要额外的锁)

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var counter = 0;
        var ts = new ThreadStart(() =>
            {

                Foo.Fired += (o, e) =>
                    {
                        counter++;
                    };
                Foo.InitialiseTimer();
                Foo.InitialiseTimer();
            });
        var t = new Thread(ts);
        t.Start();

        Thread.Sleep(30);
        Assert.AreEqual(1, counter);
    }
}

public class Foo
{
    private static System.Timers.Timer TheTimer = null;

    public static event EventHandler Fired;

    public static void InitialiseTimer()
    {
        //if (TheTimer != null)
        //{
        //    TheTimer.Stop();
        //    TheTimer = null;
        //}
        TheTimer = new System.Timers.Timer();
        TheTimer.Interval = 10;
        TheTimer.Elapsed += new ElapsedEventHandler(TheTimer_Elapsed);
        TheTimer.AutoReset = false;
        TheTimer.Start();
    }

    public static void TheTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        //Do stuff in here
        if (Fired != null)
        {
            Fired(null, null);
        }
    }
}

答案 2 :(得分:2)

如果你调用两次方法InitialiseTimer,你将创建两个定时器,每个定时器只附加一个事件处理程序,但它们可能都会经过。这不是关于方法是否静态,更多的是关于方法本身,你可以检查TheTimer是否为null,只有当它为null时才进行其余操作,所以你只分配一次。

答案 3 :(得分:1)

如果事件被注册两次,您将有两次执行。

您可以检查事件是否为空,问题将得到解决。

答案 4 :(得分:1)

静态与否,您正在重新创建计时器。因此,您可以多次调用InitialiseTimer,而无需添加多个处理程序。你最终会得到很多计时器......