Timer C# Stop() doesn't really stop - c#

I have a form which includes a textbox showing the time passing with an interval of 1 second up till 2 minutes. It is working ok. However I need the timer to stop when a round of game is over and start again when a button from another form is clicked. So I have _timer.Stop() in the timer_tick event handler and _timer.Start() in the button click event handler of Form 2.
My problem is that the timer then starts from how much time passes until I press the button on the other form and not from 0:00 again. Any Ideas?
This is the code regarding the timer:
private DateTime _myDateTime;
private System.Windows.Forms.Timer _timer;
private DateTime newDate;
public Tournament()
{
_timer = new System.Windows.Forms.Timer();
_timer.Interval = 1000;
_timer.Tick += Timer_Tick;
_myDateTime = DateTime.Now;
newDate = new DateTime();
newDate = newDate.AddMinutes(2.00);
_timer.Start();
InitializeComponent();
}
void Timer_Tick(object sender, EventArgs e)
{
var diff = DateTime.Now.Subtract(_myDateTime);
this.textBox1.Text = diff.ToString(#"mm\:ss");
DateTime dt = Convert.ToDateTime(diff.ToString());
if (newDate.Minute == dt.Minute)
{
_timer.Stop();
_myDateTime = DateTime.Now;
displayPointsOrResults();
this.textBox1.Text = diff.ToString(#"mm\:ss");
}
}
In displayPointsOrResults() I am creating instance of another form Points() so in Points form I have button 1 and I have this in its event handler apart other things which does not concern the timer: tournament.Timer1.Start();
Where I am getting the timer from the tournament class and starting it again.
What am I doing wrong?

My problem is that the timer then starts from how much time passes until I press the button on the other form and not from 0:00 again.
Well yes, it would - you're resetting _myDateTime when you stop the timer:
_timer.Stop();
_myDateTime = DateTime.Now;
You should move that second line to the point where you restart it.
Note that your title is incorrect - the timer really is stopping, in that it's not ticking any more. The timer isn't actually performing the timing, if you see what I mean - it's just a way of invoking an event handler regularly. The problem is within the event handler itself.

Ah the global vars, blessing and curse together.
Do you have resetted the _myDateTime to DateTime.Now, when you press the button?

When you stop the timer and restart it, should set the datetime to now.
_myDateTime = DateTime.Now;

Related

Stopping DispatcherTimer with a button click

When I click my stop button, my timer is still counting down, even though I tell it to stop.
My current relevant code:
I'm naming the timers here, as I need to access them for a stop/start all button as well.
namespace Row_Interface
{
public partial class MainWindow : Window
{
//Declare the timers here, so the stop all button can access them as well
DispatcherTimer motorTimer_1 = new DispatcherTimer();
TimeSpan motorCycleTime_1 = TimeSpan.FromSeconds(0);
When I click the on button, the IndividualTestStart method is called & passed the relevant parameters:
public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
{
IndividualTestStart(motorOnBtn_1, motorOffBtn_1, motorTimer_1, motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
}
When I click the off button, I'm wanting to stop that timer so the cycle never finishes:
private void motorOffBtn_1_Click(object sender, RoutedEventArgs e)
{
motorTimer_1.Stop();
motorOnBtn_1.IsEnabled = true; //Enables the start test button
motorOffBtn_1.IsEnabled = false; //Disables the stop test button
}
This is called when I click start. I'll eventually have something similar for the stop button, but I'm taking things one step at a time:
private void IndividualTestStart(Button startButton, Button stopButton, DispatcherTimer dispatcherTimer, TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
{
stopButton.IsEnabled = true; //Enables the stop button
//Set the time to run. This will be set from the database eventually.
timeSpan = TimeSpan.FromSeconds(10);
//Set up the new timer. Updated every second.
dispatcherTimer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
{
timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
startButton.IsEnabled = false; //Disables the start test button once the test is started
if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
{
dispatcherTimer.Stop(); //Stops the timer once the time has run out
startButton.IsEnabled = true; //Enables the start test button
int initialCycleCount = 0;
initialCycleCount++;
cycleCount.Text = initialCycleCount.ToString();
stopButton.IsEnabled = false;//Disables the stop button
}
timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
}, Application.Current.Dispatcher); //runs within the UI thread
dispatcherTimer.Start(); //Starts the timer
}
}
When I click the stop button, I expect the timer in the textbox to stop counting down. However, it just keeps on ticking. When I click stop, the start button is re-enabled, so I know that it's triggering the code in the event handler. But it isn't stopping the timer.
Not starting a new timer now.
New code:
public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
{
IndividualTestStart(motorOnBtn_1, motorOffBtn_1, motorTimer_1, motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
}
private void IndividualTestStart(Button startButton, Button stopButton, DispatcherTimer dispatcherTimer, TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
{
stopButton.IsEnabled = true; //Enables the stop button
//Set the time to run. This will be set from the database eventually.
timeSpan = TimeSpan.FromSeconds(10);
{
timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
startButton.IsEnabled = false; //Disables the start test button once the test is started
if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
{
dispatcherTimer.Stop(); //Stops the timer once the time has run out
startButton.IsEnabled = true; //Enables the start test button
int initialCycleCount = 0;
initialCycleCount++;
cycleCount.Text = initialCycleCount.ToString();
stopButton.IsEnabled = false;//Disables the stop button
}
timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
}; //runs within the UI thread
dispatcherTimer.Start(); //Starts the timer
}
The problem in your code is that you initialize motorTimer_1 with a DispatcherTimer that doesn't do anything, then you pass motorTimer_1 in as the dispatcherTimer parameter, and then you replace the value of the parameter with a newly created, different DispatcherTimer.
The new timer works fine, but when you call stop on motorTimer_1, nothing happens, because that's not the one that's running. You could simply assign the new DispatcherTimer directly to motorTimer_1 in IndividualTestStart(), but you've gone to great trouble to parameterize everything in IndividualTestStart() so it can work with different DispatcherTimers.
Instead, here's what we'll do: There is no reason to pass in a DispatcherTimer. IndividualTestStart() must create the DispatcherTimer in order to initialize it. OK, let's run with that. It will create a new one and return it.
private DispatcherTimer IndividualTestStart(Button startButton, Button stopButton,
TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
{
stopButton.IsEnabled = true; //Enables the stop button
//Set the time to run. This will be set from the database eventually.
timeSpan = TimeSpan.FromSeconds(10);
// Set up the new timer. Updated every second.
var dispatcherTimer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
{
timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
startButton.IsEnabled = false; //Disables the start test button once the test is started
if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
{
dispatcherTimer.Stop(); //Stops the timer once the time has run out
startButton.IsEnabled = true; //Enables the start test button
int initialCycleCount = 0;
initialCycleCount++;
cycleCount.Text = initialCycleCount.ToString();
stopButton.IsEnabled = false;//Disables the stop button
}
timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
}, Application.Current.Dispatcher); //runs within the UI thread
dispatcherTimer.Start(); //Starts the timer
return dispatcherTimer;
}
public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
{
if (motorTimer_1 == null)
{
// Create/initialize a new timer and assign it to motorTimer_1
motorTimer_1 = IndividualTestStart(motorOnBtn_1, motorOffBtn_1,
motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
}
else
{
// It's already there, just start it.
motorTimer_1.Start();
}
}
Since this is WPF, you'll want to write a viewmodel class TimerThing (think of a better name) that owns a DispatcherTimer, two commands to start it and stop it, and a public bool property that indicates whether it's running or not. IndividualTestStart() should be a method of that class. The parent viewmodel will have have an ObservableCollection<TimerThing> containing an arbitrary number of TimerThings, which will be displayed in an ItemsControl with an ItemTemplate that creates buttons bound to the Start and Stop commands. The above code will look very different, since none of the C# code will know anything about buttons: Instead, the buttons in the item template XAML will be enabled/disabled by bindings.

How do I trigger an event X seconds after a button has been clicked in a Xamarian iOS application?

I am teaching myself C# and, as part of this, am trying to develop an iOS countdown timer app that is to play a .wav sound file X seconds after a timer initiating button has been clicked as the timer value has gone from X to 0.
In an attempt to do this I have tried using the System.Timers namespace but have been unable to figure out how to program the countdown timer described above. Below is my incomplete code (code that obviously does not fulfill the above described function but might be a part of the full code that would fulfill that function):
partial void UIButton1416_TouchUpInside(UIButton sender)
{
url = NSUrl.FromFilename("Sounds/bell.wav");
bell = new SystemSound(url);
int RoundedTimerValue = Convert.ToInt32(Math.Round(TimerSlider.Value, 0));
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 60000;
timer.Enabled = true;
}
Does anyone know how to create the described countdown timer / Trigger an event X seconds after a button has been clicked?
Example Code.
Timer timer = new Timer();
timer.Interval = 60000;
timer.Elapsed += new ElapsedEventHandler((x,y) => {
//Do whatever you want
timer.Stop();
});
Put the below code in the Button Click Handler and make the timer variable global.
timer.Start();
Or you can leave everything in the Button's click handler, not a big deal.
Explanation:
The timer class has an event called Elapsed which is called when the specified number of milliseconds in the timer's Interval gets over. with the line
timer.Elapsed += new ElapsedEventHandler((x,y) => {...
we are assigning a Delegate(Virtual function) to be called when the timer is up. therefore any code within the braces{} will be called at every Timer.Interval milliseconds. we stop the timer at that time as we don't want it to keep running and generate a lot of events.
Update 2:
Normally , EventHandlers are Defined using
return_type functionName(object sender, EventArgs e);
But since the delegate is virtual, so is the parameter. x corresponds to sender and y corresponds to e.
that event handler code can also be written as below
void someFunction(object sender, ElapsedEventArgs e)
{
timer.Stop();
}
and then,
timer.Elapsed += new ElapsedEventHandler(someFunction);
As for the '=>' you can read about Lambda Expressions Here

How can I add a timer on Windows Phone 7.1?

I'm looking for a way to add a timer (or stopwatch) that will start counting from 0 the moment the application is launched or a button is clicked, and keeps counting even after the user navigates through different pages, and then be able to display how much time has passed in the last page of the application. I've been messing around with the DispatcherTimer class, but to be honest, I'm having trouble understanding it. Any help, or even a nod in the right direction would be greatly appreciated!
If you want to use a time, you could add one on the page showing time!
Add this code to the constructor or somewhere else where you want to activate the timer. (The App.StartTime is the same as i wrote in the other answer)
DispatcherTimer timer = new DispatcherTimer();
timer.Tick +=
delegate(object s, EventArgs args)
{
TimeSpan time = (DateTime.Now - App.StartTime);
this.timenow.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
};
timer.Interval = new TimeSpan(0, 0, 1); // one second
timer.Start();
You just have to store the time when your app launch and then subtract the current time from the stored value.
in your App.cs store the time when application launch:
private static DateTime _starttime = DateTime.Now;
public static DateTime StartTime
{
get
{
return _starttime;
}
}
In your page or any where you need to get the current time the application has run, you just have to subtract then current time from the stored time. I have used it in a button click handler, see below:
private void timebutton_Click(object sender, RoutedEventArgs e)
{
TimeSpan time = (DateTime.Now - App.StartTime);
this.timenow.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
}

Changing Time On MaskedTextbox

I want to design changing time on maskedtextbox in my application like windows where time changes on every second. I have set maskedtexbox1 as below:
maskedTextBox1.Text = DateTime.Now.ToShortTimeString();
which is showing current system short time but it’s not changing on every second like windows. How to do?
I'm on Visual Studio 2005, and .NET is below 3.5.
I'd use the timer and fire an event every second to update the time.
Create a timer (an instance of class Timer in the package System.Windows.Forms).
Set its frequency to 1 second (i.e. 1000 milliseconds).
Tell it what method to call when it goes off (the event handler Kaboom).
Somewhere in your executable code you do that by typing the following.
Timer ticker= new Timer();
ticker.Interval = 1000;
ticker.Tick += new EventHandler(Kaboom);
In the same class (or, if you're confident how to do it, somewhere where you can reach the code) you also create the handler for the fired event of ticking, so that the promise you made about a method to be called when the timer goes off is kept.
private void Kaboom(Object sender, EventArgs eventArgs)
{
// Execute the tickability code
MaskedTextBox1.Text = DateTime.Now.ToShortTimeString();
}
Also, don't forget to actually start your ticker when you feel that you're ready.
MyTimer.Start();
Tada!
EDIT:
For the sake of completeness, I'm also going to paste in a part of the reply of #CuaonLe (a higher threshold of competence and requirement for .NET 3.5 or newer).
Timer timer = new Timer { Interval = 1000 };
timer.Tick += (obj, args)
=> MaskedTextBox1.Text = DateTime.Now.ToLongTimeString();
timer.Start();
I guess you'll need to setup a Timer which updates your maskedTextBox1 every second.
For how to do that, please see: Add timer to a Windows Forms application
Cheers. Keith.
You can use System.Windows.Forms.Timer to update textbox value every second for example:
var timer = new Timer();
timer.Interval = 1000;
timer.Tick += delegate
{
textBox1.Text = DateTime.Now.ToLongTimeString();
};
timer.Start();

Silverlight run DispatchTimer only once

I'm trying to figure out a way in Silverlight / C# to make a DispatchTimer run only once.
I have a user form and when submitted I want to display a message for 10 seconds and then disappear and kill the DispatchTimer thread.
I know how to make a DispatchTimer that repeats:
clock.Interval = TimeSpan.FromSeconds(10);
clock.Tick += clockTick;
clock.Start();
But I want that thread to end as soon as it completes.
This should work for you:
DispatcherTimer clock = new DispatcherTimer();
clock.Interval = TimeSpan.FromSeconds(10);
clock.Tick += (object sender, EventArgs e) =>
{
clock.Stop();
// Some code here
};
clock.Start();
An anonymous event handler will also keep things "in the same place" in case you don't want to widen the scope of your DispatcherTimer object.
Stop the timer in your clockTick handler once it fires.

Categories

Resources