C# Mein Timer stoppt nicht

Smagjus schrieb:
Ergänzung ()

*Beitragsersteller ist verwirrt und hat gerade Mist geschrieben*

So viel Mist war es nun auch nicht^^

Ich habe nur im Button 1 wieder einen neuen Timer erzeugen lassen, der den anderen einfach überdeckt hat, von daher, dein Zitat von eben erklärt es schon. Nur war ich so doof und dachte man müsste das so machen und hab sie daher gleich genannt. Das hätte ich wirklich nicht machen dürfen und mich dann nur auf den myTimer beziehen, sprich per Code keinen neuen mehr erstellen.

Nur was das mit dem typecast auf sich hat raffe ich immer noch nicht^^ Beispiel wenn möglich bitte :D
 
Chef de Loup schrieb:
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.

Wenn du einen Handler für mehrere Events benutzt macht es ja Sinn, geb ich zu, aber nicht hier :)
Ergänzung ()

Nero1 schrieb:
Nur was das mit dem typecast auf sich hat raffe ich immer noch nicht^^ Beispiel wenn möglich bitte :D

Ein EventHandler hat immer die Signatur "Name(object sender, EventArgs e)".
Dabei wird das Objekt, dass das Event ausgelöst hat in das Objekt sender geboxt. Du könntest jetzt hergehen (z.B. in deinem Fall mit einem Timer) und folgendes machen:

Code:
void TimerTick(object sender, EventArgs e)
{
    Timer timer = (Timer)sender;
    timer.Stop();

    // oder
    ((Timer)sender).Stop();
}

Edit.
Den halben Post vergessen.
Obiger Code wandelt das Objekt sender, dass vom Typ "object" ist, in ein Objekt vom Typ "Timer". Das nennt man Typecast (man verwandelt einen Typen in einen anderen, um es laienhaft auszudrücken). (wenn man ganz pingelig ist, dann spricht man hier sogar von Unboxing und nicht einem Typecast ;))
 
Zuletzt bearbeitet:
Nero1 schrieb:
So viel Mist war es nun auch nicht^^
Ich hatte aber einen offensichtlichen Widerspruch darin gehabt und war ohne Test nicht dazu in der Lage, ihn aufzulösen. Ich kann hier aber gerade nicht testen, also hab ich's lieber entfernt.

Nero1 schrieb:
Nur was das mit dem typecast auf sich hat raffe ich immer noch nicht^^ Beispiel wenn möglich bitte :D
Du hast bei praktisch jedem Event diese beiden Parameter im Methodenkopf:
(object sender, EventArgs e)
Der Sender ist für uns interessant. Er enthält eine Referenz auf das Objekt, welches das Event ausgelöst hat. In unserem Fall unser Timer - praktisch oder?
Das Problem hier ist aber, dass es sich erst einmal um den Typ Objekt handelt, mit dem wir nur rudimentäre Möglichkeiten haben, wie z.B. die Methode toString() und solche Sachen, die alle Objekte bieten müssen. Da wir aber wissen, dass sich ein Timer hinter dem Ganzen verbirgt, können wir unser Objekt zu einem Timer "casten". Damit spezifizieren wir unser Objekt genauer, sodass wir letztendlich alles damit machen können, was mit dem Timer eben möglich ist.
 
Einfachstes Beispiel: Du erstellst Dir einen Timer wie in Deinem 'fehlerhaften' Code der eben nicht global ist:

Code:
private void button1_Click(object sender, EventArgs e)
{
  Timer myTimer = new Timer();
  myTimer.Interval = 1000;
  myTimer.Tick += new EventHandler(myTimer_Tick);
  myTimer.Start();
}

Du brauchst in Diesem Fall kein Timer-Objekt in deiner Form da Du sie zur Laufzeit erstellst.
Innerhalb Deines EventHandlers soll jetzt die Zeit herunter gerechnet werden und bei 0 irgendwas geschrieben werden.
Code:
private void myTimer_Tick(object sender, EventArgs e)
{
    int ZahlEingabe = Convert.ToInt32(textBox1.Text);
    ZahlEingabe -= 1;
    if (ZahlEingabe == 0)
    {
      ((Timer)sender).Stop();
      label2.Text = "Fertig!";
      label2.Refresh();
    }
    textBox1.Text = ZahlEingabe.ToString();
    textBox1.Refresh();
}

Die Funktion beendet den Timer also nach Ablauf der Zeit und da C# ja einen Garbage Collector hat musst Du nicht mal aufraeumen. In diesem Beispiel wuerde das Ausschalten des Timers per Button natuerlich nicht funktionieren, da der Timer nicht bekannt/sichtbar ist fuer alle anderen Funktionen.
Du koenntest den Eventhandler jetzt auch fuer andere Timer benutzen, da es ihm egal ist welcher Timer gemeint ist, denn das Timer-Objekt selbst ist ja als Parameter sender uebergeben worden.
 
Also hieße das in meinem Beispiel mit dem myTimer, ich könnte mit dem Befehl (in der _Tick) stoppen?

((myTimer)sender).stop;
 
Nero1 schrieb:
Also hieße das in meinem Beispiel mit dem myTimer, ich könnte mit dem Befehl (in der _Tick) stoppen?

((myTimer)sender).stop;

((Timer)sender).Stop();

In den Klammern steht immer ein Typ, wie z.B. Timer, kein Variablenname.
 
Ok anscheinend also nicht, aber wenn ich das richtig verstehe gilt das

((Timer)sender).stop();

ja nur für den Timer in der _Tick. Wie könnte ich da mit mehreren arbeiten wie es vorhin gesagt wurde?? Dass ich ihn mehrere mal verwenden kann oder so ähnlich?

Bzw sehe ich grad keinen Mehrwert wenn ich immer wieder myTimer.Start() oder .Stop() verwenden würde o.O
 
Hm, Typecast funktioniert nach dem Prinzip: Sag mir was fuer ein Typ ich bin. myTimer ist eine Instanz vom Typ Timer. Sprich Du musst Timer verwenden.

Object ist der einfachste Klassentyp, so wie man Genom als einfachsten Typ des Lebens bezeichnen koennte. Wenn Du aber weisst, dass die Referenz einem bestimmten Klassentyp (zB Mensch) entspricht, dann kannst Du diese Referenz auch per Typecast sagen als was sie agieren soll. Du castest also nicht auf einen spezifischen Ableger Klaus sondern auf den Klassentyp Mensch. Das der uebergebene Mensch Klaus ist, interessiert Dich nicht, da Du nur die Funktionen nutzen willst, die jeder Mensch besitzt.
Vielleicht ist es so etwas verstaendlicher *g*

Edit:
Das was Du mehrmals verwenden kannst ist die EventHandler Funktion selbst. Sofern Du dort mit der uebergebenen Referenz arbeitest, ist es der Funktion egal ob myTimer, yourTimer oder ourTimer das Ereignis ausgeloest hat. Die Funktion weiss in jedem Falle: Der Timer der mich ausgeloest hat den muss ich gegebenenfalls auch stoppen.
 
Zuletzt bearbeitet:
Wir haben dich noch nicht ganz auf dem richtigen Weg.

Du kannst deinen Timer beliebig oft und von überall in deiner Klasse starten oder stoppen, wenn du ihn global definierst. Das machst du, indem du ihn entweder in deiner UI oder ganz zu Beginn deiner Klasse anlegst. So legst du z.B. einen globalen Timer über deine Klasse an.

Code:
public partial class Form1 : Form{
private Timer GlobalerTimer = new Timer();
//Code
//Code
//...
}
Dann kannst du deinen Timer immer über GlobalerTimer.start(); bzw. GlobalerTime.stop(); anhalten und stoppen, wann immer es dir lieb ist.

Auf Casting kannst du in deinem Anwendungsszenario komplett verzichten.

Eventuell würde es dir helfen ein wenig über Gültigkeitsbereiche von Variablen zu lesen oder es einfach auszuprobieren.
 
Ok, danke euch. Ich glaube jetzt hab ich es verstanden. Mal sehen wie ich in Zukunft alles klappt, ich melde mich wenn ich wieder fragen hab^^

Nur eine würde mich noch interessieren, angenommen ich habe 3 verschiedene Timer, jeden in einer

private void (TimerName)_Tick(object sender, EventArgs e)
{
}

einzeln mit Anweisungen bestückt, und ich würde beispielsweise einen Button machen und schreiben:

((Timer)sender).Stop();

Stoppen dann alle Timer zugleich?

EDIT:

sorry, iwie glaub ich is das n Denkfehler, ich kann das sender bloß dann für jeden einzeln verwenden oder?
 
Zuletzt bearbeitet:
In der ButtonClick Funktion verweist der Parameter sender nicht auf einen Timer sondern auf den Button, der das Click ausgeloest hat. Du kannst Dort also nicht den typecast anwenden sondern musst ueber den globalen Bezeichner gehen.
 
Puh is das kompliziert o.O xD

na gut, immerhin weiß ich jetz (denke ich) ganz gut Bescheid^^

Danke euch allen ;)
 
Zurück
Oben