none
Timer löst nach zweiten Start das Event doppelt aus ?

    Frage

  • Moin,

    hab ein kleines Problem, Mit einem Button Klick wird ein Timer gestartet und auch wieder beendet. Doch wenn ich das ganze ein zweites mal mache, sprich Starten - Stoppe - Starten ... Dann macht er alles was im Event timer1_Tick drin steht zweimal.

    Habt ihr eine Lösung wie ich das beheben kann? Hab es auch schon mit "timer1.eneabled = false oder true" probiert. Mit "timer1.Start()" und "timer1.Stop()" geht es ebenfalls nicht...

    namespace KeysSenden
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            bool Clicked = false;
            Timer t1 = new Timer();
    
            private void BtnStart_Click(object sender, EventArgs e)
            {
                if (Clicked == true)
                {
                    t1.Enabled = false;
                    this.BtnStart.BackColor = Color.OrangeRed;
                    Clicked = false;
                }
                else
                {
                    this.BtnStart.BackColor = Color.GreenYellow;    
                    t1.Tick += t1_Tick;
                    t1.Interval = 3000;
                    t1.Enabled = true;
                    Clicked = true;
                }
            }
    
            void t1_Tick(object sender, EventArgs e)
            {
                SendKeys.SendWait("{Enter}");
            }

    Mfg!


    Mittwoch, 23. Oktober 2013 18:06

Antworten

  • Hallo,

    registriere das Tick Ereignis nur einmal. Am einfachsten erzeuge das Ereignis im Konstruktor und schalte nur Enable um:

        Timer t1;
    
        public Form1()
        {
            InitializeComponent();
            
            t1 = new Timer();
            t1.Tick += t1_Tick;
            t1.Interval = 3000;
        }
    
        private void BtnStart_Click(object sender, EventArgs e)
        {
            if (t1.Enabled)
            {
                t1.Enabled = false;
                this.BtnStart.BackColor = Color.OrangeRed;
            }
            else
            {
                this.BtnStart.BackColor = Color.GreenYellow;    
                t1.Enabled = true;
            }
        }
    

    (Clicked habe ich gestrichen, denn Enabled sollte hier gleiche Dienste leisten).

    Gruß Elmar

    • Als Antwort markiert XxDeadLiinexXx Mittwoch, 23. Oktober 2013 18:17
    Mittwoch, 23. Oktober 2013 18:12
    Beantworter
  • Hallo,
    das Problem besteht darin, das du das Tick-Event mit jedem Buttonklick neu registrierst. Abbonniere das Event einfach im Konstruktor und lösche diese Zeile aus dem Klick-Handler.
            public Form1()
            {
                InitializeComponent();
    t1.Tick += t1_Tick; }
    PS: Zum absichtlichen deaktivieren kannst du entweder -= nutzen oder den Timer über new komplett neu instanzieren.

    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.


    Mittwoch, 23. Oktober 2013 18:14
    Moderator
  • Hallo,

    "müssen" tut man nicht, aber sinnvollerweise sucht man sich eine Stelle aus, die nur einmalig durchlaufen wird. Der Konstruktor ist in diesem Falle eine günstige Stelle.

    Alles andere läuft auf komplexeren Code hinaus; das Jonglieren mit Hilfsvariablen (wie auch clicked) oder hier das Abmelden des Ereignisses beim Deaktivieren - da ist KISS besser ;)

    Gruß Elmar

    • Als Antwort markiert XxDeadLiinexXx Mittwoch, 23. Oktober 2013 18:31
    Mittwoch, 23. Oktober 2013 18:30
    Beantworter

Alle Antworten

  • Hallo,

    registriere das Tick Ereignis nur einmal. Am einfachsten erzeuge das Ereignis im Konstruktor und schalte nur Enable um:

        Timer t1;
    
        public Form1()
        {
            InitializeComponent();
            
            t1 = new Timer();
            t1.Tick += t1_Tick;
            t1.Interval = 3000;
        }
    
        private void BtnStart_Click(object sender, EventArgs e)
        {
            if (t1.Enabled)
            {
                t1.Enabled = false;
                this.BtnStart.BackColor = Color.OrangeRed;
            }
            else
            {
                this.BtnStart.BackColor = Color.GreenYellow;    
                t1.Enabled = true;
            }
        }
    

    (Clicked habe ich gestrichen, denn Enabled sollte hier gleiche Dienste leisten).

    Gruß Elmar

    • Als Antwort markiert XxDeadLiinexXx Mittwoch, 23. Oktober 2013 18:17
    Mittwoch, 23. Oktober 2013 18:12
    Beantworter
  • Hallo,
    das Problem besteht darin, das du das Tick-Event mit jedem Buttonklick neu registrierst. Abbonniere das Event einfach im Konstruktor und lösche diese Zeile aus dem Klick-Handler.
            public Form1()
            {
                InitializeComponent();
    t1.Tick += t1_Tick; }
    PS: Zum absichtlichen deaktivieren kannst du entweder -= nutzen oder den Timer über new komplett neu instanzieren.

    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.


    Mittwoch, 23. Oktober 2013 18:14
    Moderator
  • Super, funktioniert! Danke!!!

    Muss ich Events immer in "InitializeComponent();" schreiben?

    Weil der globel Timer kommt ja danch :-) 

    Mfg!

    Mittwoch, 23. Oktober 2013 18:17
  • Hallo,

    "müssen" tut man nicht, aber sinnvollerweise sucht man sich eine Stelle aus, die nur einmalig durchlaufen wird. Der Konstruktor ist in diesem Falle eine günstige Stelle.

    Alles andere läuft auf komplexeren Code hinaus; das Jonglieren mit Hilfsvariablen (wie auch clicked) oder hier das Abmelden des Ereignisses beim Deaktivieren - da ist KISS besser ;)

    Gruß Elmar

    • Als Antwort markiert XxDeadLiinexXx Mittwoch, 23. Oktober 2013 18:31
    Mittwoch, 23. Oktober 2013 18:30
    Beantworter
  • Also InitialisizeComponent sorgt dafür, das das eigentliche Fensterdesign (Buttons etc.) erstellt wird. Danach kannst du beliebig viele Dinge mit in den Konstruktor rein packen, die beim erstellen ausgeführt werden sollen. (Bei zugriffen auf Controls hinter InitialisizeComponent, sonst ist es egal)

    Dinge, die sowieso häufig in der ganzen Klasse verwendet werden, wie dein Timer, die kann man im Konstruktor initalisieren (= new ...) und Eigenschaften sowie Eventhandler zuweisen.

    Machen muss man es nicht. Man kann es auch so machen wie in deiner Frage, dann ist aber beim erneuten Buttonklick das deabbonnieren erforderlich:

     t1.Tick -= t1_Tick;
    Aber wie gesagt, das braucht man hier nicht, da eine Zeile im Konstruktor reicht.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Mittwoch, 23. Oktober 2013 18:33
    Moderator