обработчик события c # добавляется дважды - PullRequest
1 голос
/ 03 марта 2011

Это вымышленный пример, но я бродил, что произойдет, если функция 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
    }

Я собирался использовать ниже, чтобы предотвратить это

Добавлен ли обработчик событий?

Спасибо, Ричард

Ответы [ 5 ]

5 голосов
/ 03 марта 2011

Если вы зарегистрируете обработчик событий дважды, он будет вызываться дважды при каждом возникновении события.

Это не изменится, если вы сделаете TheTimer_Elapsed статическим, потому что вы все равно будете хранить две ссылки на этот статический метод.

В большинстве случаев нет необходимости писать сложные вещи вроде того, что написал Блэр Конрад в вопросе, на который вы ссылались. Только не забывайте использовать -= каждый раз, когда у вас есть +=, и вы будете в безопасности.

4 голосов
/ 03 марта 2011

Я думаю, что следующее демонстрирует сценарий и действительно запускается дважды, а также предлагает простое изменение (закомментированный код) в метод Init, который должен исправить поведение.(Кстати, потокобезопасен, потребуются дополнительные блокировки)

[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 голосов
/ 03 марта 2011

если вы вызовете метод InitialiseTimer дважды, вы создадите два таймера, к каждому из которых будет прикреплен только один обработчик события, но они могут истечь оба.Дело не в том, чтобы метод был статическим или нет, а в том, что касается самого метода, вы можете проверить, является ли TheTimer нулевым, и делать все остальное, только если он нулевой, поэтому вы назначаете его только один раз.

1 голос
/ 03 марта 2011

Статический или нет, вы воссоздаете таймер. Таким образом, вы можете вызывать InitialiseTimer много-много раз, не добавляя более одного обработчика. Хотя у вас будет много таймеров ...

1 голос
/ 03 марта 2011

Если событие зарегистрировано дважды, у вас будет два исполнения.

Вы можете проверить, является ли событие пустым, и проблема будет решена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...