C# Mein Timer stoppt nicht

Fasko

Lt. Junior Grade
Registriert
Jan. 2011
Beiträge
473
Hallo,

wenn der Benutzer zum ersten Mal auf meinen Button klickt soll der Timer starten. Beim zweiten soll der Timer stoppen. Allerdings stoppt der Timer nicht. Warum?

Code:
 private void btn_autoAkt_Click(object sender, EventArgs e)
        {
            
            
            // Timer
            
            this.newTimer.Interval = 2000;
            this.newTimer.Tick += new EventHandler(newTimer_Tick);
            //newTimer.Enabled = true;
            // Überprüft ob der Timer ein oder ausgeschaltet ist
           if (this.newTimer.Enabled == true)
            {
                newTimer.Enabled = false;
            }
            else
            {
                this.newTimer.Enabled = true;
              
            }
            
        }

Gruß

Fasko
 
Ich weiss grad nicht ob ich richtig liege, aber du solltest eine globale Variable erstellen, zB globTimer, diese initialisierst du mit 'false', wenn du nun den Button klickst setzt du globTimer = !globTimer !

Dementsprechend hast du eine Abbruchbedingung!
 
Marguth schrieb:
Code:
this.newTimer.Stop();

Erstaunlicherweise hat es damit funktioniert. Aber warum hat
this.newTimer.Enable = false;

nicht funktioniert?
 
Laut msdn macht es keinen Unterschied, aber aus meiner Sicht:
Warum sollten die eine Methode implementieren wenn die nur 1 public Property ändert? ;)

Ich persönlich arbeite viel mit Timern und benutze nur start/stop, hatte damit nie Probleme, überprüfen dann natürlich mit enabled.

Ehrlich gesagt habe ich aber keine Ahnung wieso genau da jetzt enabled nicht greift, und wann es nicht greift etc. werde mal gleich meinen Guru fragen :)

In meiner kleinen Testanwendung funktioniert enabled einwanfrei...

Code:
        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Enabled = !timer1.Enabled;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            MessageBox.Show("Hallo Welt");
        }

Du hast sowieso ein größeres Problem:
Weil du dem NewTimer.Tick mehrere events zuweißt.
Jedes mal wenn du auf den button klickst kommt eins dazu => Wenn du startest, stoppst und
ihn dann wieder startest wird das event alle zwei Sekunden drei Mal ausgeführt!

Code:
            this.newTimer.Interval = 2000;
            this.newTimer.Tick += new EventHandler(newTimer_Tick);

Sollte in die Methode wo du "netTimer" erstellst oder ggf. in das Form_Load.

Am einfachsten:
Statt alles direkt per Code zu machen - einfach ein Timer-Control auf die Form zu ziehen und im Designer anpassen (Doppelklick auf timer => Erstellt Tick-Event + weißt es dem Timer im Markup zu).
 
Zuletzt bearbeitet von einem Moderator:
Hi,

habe dasselbe Problem. Auf Arbeit arbeite ich mich derzeit in C# ein und einer meiner Kollegen (erfahrener Programmierer der Firma) sieht auch keine Fehler.
Normalerweise sollte mein Timer stoppen, sobald mein Countdown 0 erreicht hat...tut er aber nicht -.-

Kurze Info:

Ziel soll sein, man hat ein Textfeld in welches man eine beliebige Zahl eingibt, und wenn man auf den button1 klickt (Start) soll es von dieser Zahl an runterzählen, bis es 0 erreicht und dannder Timer (im 1 sec Takt) wieder stoppen. Mit dem zweiten Button soll man den Vorgang abbrechen können.


Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsTest_Weiterentwicklung
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void myTimer_Tick(object sender, EventArgs e)
        {
            int ZahlEingabe = Convert.ToInt32(textBox1.Text);

            ZahlEingabe -= 1;

            if (ZahlEingabe == 0)
            {
                myTimer.Stop();
                label2.Text = "Fertig!";
                label2.Refresh();
                //textBox1.Text = "Ende";
                //textBox1.Refresh();
            }

            textBox1.Text = ZahlEingabe.ToString();

            textBox1.Refresh();


        }

        private void button1_Click(object sender, EventArgs e)
        {
            Timer myTimer = new Timer();

            myTimer.Interval = 1000;

            myTimer.Tick += new EventHandler(myTimer_Tick);

            myTimer.Start();


        }

        private void button2_Click(object sender, EventArgs e)
        {
            myTimer.Stop();
            label2.Text = "Abgebrochen!";
            label2.Refresh();
        }


    }
}


Muss ich irgendwelche Einstellungen im Visual Studio 10 beachten? Habe ich was übersehen? Bitte helft mir :(

Lg Nero
 
myTimer ist ein globales Objekt?

In dem timer-Event solltest Du das Dir uebergebene Objekt auch nutzen: myTimer_Tick(object sender, EventArgs e)
Einfach einen typecast von sender zu Timer und die Funktion Stop() nutzen. Zaehlt das System denn runter auf 0? Wenn ja und trotz der Aenderung es noch nicht funktioniert dann teste auf > oder != anstatt auf ==.
 
Nero1 schrieb:
Code:
        private void button2_Click(object sender, EventArgs e)
        {
            [COLOR=Red]myTimer.Stop();[/COLOR]
            label2.Text = "Abgebrochen!";
            label2.Refresh();
        }
So wie ich das sehe, müsste myTimer.Stop(); eine Exception werfen. Du hast deinen Timer in der button1_Click definiert und versuchst ihn außerhalb seines Gültigkeitsbereichs zu stoppen. Das kann doch garnicht funktionieren oder sehe ich das falsch?
 
Nero1 schrieb:
... und einer meiner Kollegen (erfahrener Programmierer der Firma) sieht auch keine Fehler.

Oha.

Nero1 schrieb:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsTest_Weiterentwicklung
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void myTimer_Tick(object sender, EventArgs e)
        {
            int ZahlEingabe = Convert.ToInt32(textBox1.Text);

            ZahlEingabe -= 1;

            if (ZahlEingabe == 0)
            {
                myTimer.Stop();
                label2.Text = "Fertig!";
                label2.Refresh();
                //textBox1.Text = "Ende";
                //textBox1.Refresh();
            }

            textBox1.Text = ZahlEingabe.ToString();

            textBox1.Refresh();


        }

        private void button1_Click(object sender, EventArgs e)
        {
            Timer myTimer = new Timer();

            myTimer.Interval = 1000;

            myTimer.Tick += new EventHandler(myTimer_Tick);

            myTimer.Start();


        }

        private void button2_Click(object sender, EventArgs e)
        {
            myTimer.Stop();
            label2.Text = "Abgebrochen!";
            label2.Refresh();
        }


    }
}

Der Click-Eventhandler für Button1 erzeugt einen neuen Timer, der genauso heißt wie der Timer, den du in der UI hinzugefügt hast. D.h. der Timer im Event-Handler verdeckt den anderen Timer. Wenn du nun myTimer.Start() sagst, ist das ein anderer Timer wie der aus myTimer.Stop().


Code:
private void button1_Click(object sender, EventArgs e)
{
        myTimer.Start();
}

So sollte es gehen. Den EventHandler kannst du auch in der UI zuweisen. Wenn es code-behind sein soll, dann bitte nicht in einem Click-Handler. Der Grund wurde weiter oben schon genannt.
 
Chef de Loup schrieb:
myTimer ist ein globales Objekt?

In dem timer-Event solltest Du das Dir uebergebene Objekt auch nutzen: myTimer_Tick(object sender, EventArgs e)
Einfach einen typecast von sender zu Timer und die Funktion Stop() nutzen. Zaehlt das System denn runter auf 0? Wenn ja und trotz der Aenderung es noch nicht funktioniert dann teste auf > oder != anstatt auf ==.

Smagjus schrieb:
So wie ich das sehe, müsste myTimer.Stop(); eine Exception werfen. Du hast deinen Timer in der button1_Click definiert und versuchst ihn außerhalb seines Gültigkeitsbereichs zu stoppen. Das kann doch garnicht funktionieren oder sehe ich das falsch?

Der myTimer wird in button1 gestartet und geht dann im Ereignis myTimer_Tick weiter. Was den Gültigkeitsbereich betrifft, wenn er nicht gültig wäre könnte ich ihn doch gar nicht auswählen oder? Intellisense gibt mir ja die Vorlage und es kommt auf keine Fehlermeldung...

@Chef, leider bin ich wirklich Anfänger und versuche weiter zu lernen, aber wie ich sender zu Timer ändern soll (bzw den Typ) und dann auch noch nutzen, da blick ich noch net durch^^ Wär nett wenn du ein kleines Beispiel hättest oder das mehr erläutern könntest.

Problem ist halt, er zählt ordnungsgemäß runter, bis zu 0, zeigt dann auch im Label "Fertig" an. Nur dann rechnet er einfach weiter, sprich er stoppt nicht bei

Code:
if (ZahlEingabe == 0)
            {
                myTimer.Stop();

sondern rechnet einfach munter weiter bis ich das Programm beende.

Auch sonst, ich bin neu im Gefilde und würde der Einfachheit halber bitten ein wenig Rücksicht hinsichtlich der Begriffe und Vorschläge zu nehmen, ich versteh zwar einiges aber noch nich so viel auf Anhieb wie ein jahrelanger C#-Programmierer, ich muss erst reinkommen ;) (sind ja erst 3 Wochen^^)
Ergänzung ()

holy schrieb:
Der Click-Eventhandler für Button1 erzeugt einen neuen Timer, der genauso heißt wie der Timer, den du in der UI hinzugefügt hast. D.h. der Timer im Event-Handler verdeckt den anderen Timer. Wenn du nun myTimer.Start() sagst, ist das ein anderer Timer wie der aus myTimer.Stop().


Code:
private void button1_Click(object sender, EventArgs e)
{
        myTimer.Start();
}

So sollte es gehen. Den EventHandler kannst du auch in der UI zuweisen. Wenn es code-behind sein soll, dann bitte nicht in einem Click-Handler. Der Grund wurde weiter oben schon genannt.

Tatsache, jetz gehts o.O

Dazu sei gesagt, er hat es zumindest nich erkannt und is auch mehr in Delphi unterwegs^^ Vlt hat ers auch übersehen, er macht mehreres und nicht nur sowas. Aber egal jetzt, kann mir jemand erklären wie der Timer dann erstellt wird/seine Wirkung bekommt? Allein schon durch die myTimer_Tick?
 
Zuletzt bearbeitet:
Normalerweise machst Du das so: ((Timer *)sender).Stop();

Ich bin aber mehr in der C++ als in der C# Ecke beheimatet daher weiss ich nicht ob das so 100% stimmt. Und das Problem hat holy ja schon beschrieben mit dem 'Ueberschreiben'.
 
Chef de Loup schrieb:
Normalerweise machst Du das so: ((Timer *)sender).Stop();

Ich bin aber mehr in der C++ als in der C# Ecke beheimatet daher weiss ich nicht ob das so 100% stimmt. Und das Problem hat holy ja schon beschrieben mit dem 'Ueberschreiben'.

sender ist vom Typ Button, dass geht auch in C++ nicht ^^.


Nero1 schrieb:
..., kann mir jemand erklären wie der Timer dann erstellt wird/seine Wirkung bekommt? Allein schon durch die myTimer_Tick?[/COLOR]

Nein. myTimer_Tick ist ein EventHandler.
Wenn du in der UI ein Objekt in den Designer ziehst, wird in der Form.Designer.cs Datei der entsprechende Code eingefügt. Beim kompilieren werden die Dateien (deine Form.cs und die automatisch generierte Form.Designer.cs) dann zusammen gefügt.
Daher auch das "partial class".
 
Wenn bei der Funktion: private void myTimer_Tick(object sender, EventArgs e)
sender vom Typ Button ist, dann wuerd ich aber C# in die Tonne werfen ;)
 
Chef de Loup schrieb:
Wenn bei der Funktion: private void myTimer_Tick(object sender, EventArgs e)
sender vom Typ Button ist, dann wuerd ich aber C# in die Tonne werfen ;)

:D

Sein Stop() steht aber in einem EventHandler für ein ButtonClick-Event ;)
 
Aehem...
Code:
 private void myTimer_Tick(object sender, EventArgs e)
{
int ZahlEingabe = Convert.ToInt32(textBox1.Text);
 
ZahlEingabe -= 1;
 
if (ZahlEingabe == 0)
{
myTimer.Stop();
label2.Text = "Fertig!";
label2.Refresh();
//textBox1.Text = "Ende";
//textBox1.Refresh();
}
 
textBox1.Text = ZahlEingabe.ToString();
 
textBox1.Refresh();
 
 
}

Er hat zwei Moeglichkeiten des Stopps: Einmal per Button und einmal per Timer-Event. Und im Timer-Event soll er bitte per typecast arbeiten anstatt per globaler Variablen, da man so die Funktion auch gleich mehrfach verwenden kann.
 
Oh mann lustig das zu lesen^^

Mittlerweile hab ich ihm das gezeigt und er wusste es auch, hatte vorhin aber gar nicht darauf geachtet.

Wenn ich den Timer in das Designfeld ziehe und das Tick Event zuordne/erstelle wird das wohl schon alles automatisch erstellt, sodass ich gar keinen mehr generieren muss. Dachte das is anders, vlt weil ich das in diversen Beispielen so gesehen habe (was aber wohl für andere Anwendungsarten geacht war, ka^^).

Immerhin gehts jetzt und ich denke ich weiß auch warum. Aber echt DANKE und Respekt an euch, die so schnell und kompetent beraten, war echt super ;)

DANKE :)
 
Chef de Loup schrieb:
Aehem...
Er hat zwei Moeglichkeiten des Stopps: Einmal per Button und einmal per Timer-Event. Und im Timer-Event soll er bitte per typecast arbeiten anstatt per globaler Variablen, da man so die Funktion auch gleich mehrfach verwenden kann.

OK, das zweite Stop hab ich nichtmals gesehen. Wie auch immer, den Sinn von dem Typecast versteh ich nicht. Man kann auch ganz einfach myTimer.Stop sagen. Da ist überhaupt kein Cast notwendig.
 
Ergänzung ()

*Beitragsersteller ist verwirrt und hat gerade Mist geschrieben*
 
Zuletzt bearbeitet:
Ja, natuerlich kann er auch direkt myTimer.Stop() nehmen aber wieso nimmt man nicht das uebergebene Objekt von dem man weiss das es der Ursprung ist, den man auch anhalten will? Wenn er die gleiche Funktion mit einem zweiten Timer verwenden will, dann muss er den Quelltext aendern. Mit typecast kann es ihm vollkommen egal sein und vor allem: Er muss nicht mal wissen ob das Objekt global bzw. Sichtbar ist er hat ja eine direkte Referenz mitbekommen.
 
Zurück
Oben