I am working on stopwatch. If I select the start button the timer is running fine. But when I press the button again with the following code. Then the timer starts from beginning 00:00:00. I want to pause the timer and if I press it, again it should start from the paused time, not from the beginning time. How to do this task? Any other ideas are also accepted.
private void Timer_Tick(object sender, EventArgs e)
{
TimeSpan runTime = TimeSpan.FromMilliseconds(System.Environment.TickCount - _startTime);
timeLabel.Text = runTime.ToString(#"hh\:mm\:ss");
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
if (_timer.IsEnabled)
{
_watcher.Stop();
_timer.Stop();
StartButton.Content = "Start";
}
else
{
_watcher.Start();
_timer.Start();
_startTime = System.Environment.TickCount;
StartButton.Content = "Stop";
}
}
Just get the timer time when you click on stop button and change your code when you click on start button.
Start button :
Check if _refreshTimeTimer is not null
well
if(_refreshTimeTimer != null){
Timer t = new timer(_refreshTimeTimer );
// Start new timer
_refreshTimeTimer = null;
}else{
if (_timer.IsEnabled)
{
_watcher.Stop();
_timer.Stop();
StartButton.Content = "Start";
}
else
{
_watcher.Start();
_timer.Start();
_startTime = System.Environment.TickCount;
StartButton.Content = "Stop";
}
}
Stop button :
_refreshTimeTimer = _timer.getTime();
You have to declare dispatcher time , run timer at what time do you want to pause then start your first time add dispatcher timer value it will start from before paused time.
Related
i'm trying to implement a simple countdown using Timer (using https://www.geoffstratton.com/cnet-countdown-timer code). it does work if i run the timer once but if i stop the timer or the timer goes to 00:00 the next time i'll start it, it will go 2x faster. if i stop it and start it again it will go 3x faster.
(my explaination may be not clear, i did a gif that demonstrate the problem)
https://media.giphy.com/media/fQr7sX6LNRECvQpCYP/giphy.gif
i'm very novice at c#, i usually figure things out but i cant get what's happening here.
I included the timer code. if somebody can help me with this it would be awesome!
Thanks !!!
private void btnStartTimer_Click(object sender, EventArgs e)
{
if (txtTimer.Text == "00:00")
{
MessageBox.Show("Please enter the time to start!", "Enter the Time", MessageBoxButtons.OK);
}
else
{
string[] totalSeconds = txtTimer.Text.Split(':');
int minutes = Convert.ToInt32(totalSeconds[0]);
int seconds = Convert.ToInt32(totalSeconds[1]);
timeLeft = (minutes * 60) + seconds;
btnStartTimer.Enabled = false;
btnCleartimer.Enabled = false;
txtTimer.ReadOnly = true;
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Start();
}
}
private void btnStopTimer_Click(object sender, EventArgs e)
{
timer1.Stop();
timeLeft = 0;
btnStartTimer.Enabled = true;
btnCleartimer.Enabled = true;
txtTimer.ReadOnly = false;
}
private void btnCleartimer_Click(object sender, EventArgs e)
{
txtTimer.Text = "00:00";
}
private void timer1_Tick(object sender, EventArgs e)
{
if (timeLeft > 0)
{
timeLeft = timeLeft - 1;
// Display time remaining as mm:ss
var timespan = TimeSpan.FromSeconds(timeLeft);
txtTimer.Text = timespan.ToString(#"mm\:ss");
// Alternate method
//int secondsLeft = timeLeft % 60;
//int minutesLeft = timeLeft / 60;
}
else
{
timer1.Stop();
SystemSounds.Exclamation.Play();
MessageBox.Show("Time's up!", "Time has elapsed", MessageBoxButtons.OK);
}
}
You need to unsubscribe from the event in your btnStopTimer_Click method:
timer1.Tick -= timer1_Tick;
You are adding the event to Count every time you start the timer. As a result, the first time you call it there is only one event, the second time two events and so on. As a result, you first go down one second, then two,....
I would recommend creating the timer separately and just call Start and Stop.
Alternativ, user Dmitry Korolev answered a good Approach if you don't want to create the timer somewhere else
timer1.Tick -= timer1_Tick;
So in my windows form I have a button that you click to start a timer, I only want the timer to start when the door is closed.
In my wm class I have
public bool doorState()
{
if (doorClosed == true)
{
return true;
}
return false;
}
And in the main code I have
private void button3_Click(object sender, EventArgs e)
{
if (wm.doorState())
{
timer1.Start();
}
}
However when I press button 3 now the timer will not start regardless of whether the door is closed.
Any help greatly appreciated.
Just set the timer to enabled to true or false
private void button3_Click(object sender, EventArgs e)
{
if (wm.doorState())
{
timer1.Enabled = true;
timer1.Start();
}
else
{
timer1.Enabled = false;
}
}
And don't forget to set the timer interval to the properties like Interval to 1000 if you want the tick for every second.
or you can set it in code behind like:
timer1.Interval = 1000;
NOTE: This question is related to this one as well
How to create an advanced countdown timer
I have a timer which is activated by a button that starts the countdown of the supposed activity. But I have a problem, when I press the same button again, the program must use another time (specified inside a datagrid) and start the countdown again, and if I press the button again, another time and so on.
Shall I use multiple timers or is there a way I can use the same timer, but with new ("reset") values if I press the button?
(If you guys want me to show more of the code, just tell me I'll post here)
private bool timeSet2 = false;
int f = 1;
private void timer3_Tick(object sender, EventArgs e)
{
DateTime timeConvert;
DateTime dateTime = DateTime.Now;
string timeOp = dataGridView1.Rows[f].Cells[2].Value + "";
f++;
if (!timeSet2) // only get the value once
{
DateTime.TryParse(timeOp, out timeConvert);
milliSecondsLeft = (int)timeConvert.TimeOfDay.TotalMilliseconds;
timeSet2 = true;
}
milliSecondsLeft = milliSecondsLeft - 1000;
if (milliSecondsLeft > 0)
{
var span = new TimeSpan(0, 0, 0, 0, milliSecondsLeft);
lblLeft.Text = span.ToString(#"hh\:mm\:ss");
}
else
{
timer3.Stop();
}
I need to fit a button right here so if I press it, my program will start another countdown. But I don't know if I'll have to create another time for this.
You can use the same timer and reset it for each countdown. But I think you are misunderstanding the the functionality of the timer. The timer_Tick event occurs every time the interval of the timer has elapsed. Update the milliSecondsLeft variable on your button click event.
You have to move some code to the button_Click event.
private void button1_Click(object sender, EventArgs e)
{
milliSecondsLeft = Convert.ToInt32(dataGridView1.Rows[f].Cells[2].Value)*1000;
f++;
timer3.Start();
}
Your timer_Tick event would then look like:
private void timer3_Tick(object sender, EventArgs e)
{
milliSecondsLeft = milliSecondsLeft - 1000;
if (milliSecondsLeft > 0)
{
var span = new TimeSpan(0, 0, 0, 0, milliSecondsLeft);
lblLeft.Text = span.ToString(#"hh\:mm\:ss");
}
else
{
timer3.Stop();
}
}
Some other things:
Are you sure you want to start with the second column of your dataGridView with int f = 1;
I did not understand your time conversion so I changed it. Now it expects the countdown time in your dataGridView to be in seconds. But perhaps your code is right for your purpose
In this code after starting timer again it starts from the current value instead of the vale it stopped. How to pause this timer?
public Page1()
{
InitializeComponent();
_rnd = new Random();
_timer = new DispatcherTimer();
_timer.Tick += new EventHandler(TimerTick);
_timer.Interval = new TimeSpan(0, 0, 0, 1);
}
void TimerTick(object sender, EventArgs e)
{
var time = DateTime.Now - _startTime;
txtTime.Text = string.Format(Const.TimeFormat, time.Hours, time.Minutes, time.Seconds);
}
public void NewGame()
{
_moves = 0;
txtMoves.Text = "0";
txtTime.Text = Const.DefaultTimeValue;
Scrambles();
while (!CheckIfSolvable())
{
Scrambles();
}
_startTime = DateTime.Now;
_timer.Start();
//GridScrambling.Visibility = System.Windows.Visibility.Collapsed;
}
private void Pause_Click(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
NavigationService.Navigate(new Uri("/Page4.xaml", UriKind.Relative));
_timer.Stop();
}
private void Play_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
_timer.Start();
}
As this says that the Stop method only changes the IsEnabled property and this says that this property only prevents the Tick event to be raised, I don't think that there is a method to simply 'pause' the timer. The best way is to reinitialize the timer each time you have "paused" it, if you really want it to start clean again.
But I do not think that this is you real problem. When you pause your game the timer stops working. When you continue it the timer starts working again. When you now try the calculate the time from THIS moment till the start time, then you make a big mistake: you have to ignore the paused time. Because when you play the game 2s, then pause it for 10s and then continue the game, the timer shows 12s, instead of 2s, doesn't it? Maybe you should store the paused times in a variable and substract that from the real game time.
i have a strange situation.
please see the backgroundWorker5_RunWorkerCompleted event:
private void backgroundWorker5_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnStartAdventures.Text = "Start Adventure";
btnStartAdventures.Enabled = true;
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
return;
}
if (e.Cancelled)
{
lblStatusValueInAdventures.Text = "Cancelled...";
}
else
{
lblStatusValueInAdventures.Text = "Completed";
timer1.Enabled = true;
timer1.Start();
// MessageBox.Show("start timer");
Thread.Sleep((int.Parse(txtDelayInAdventures.Text)) * 60000);
//MessageBox.Show("end timer");
timer1.Enabled = false;
timer1.Stop();
lblTimer.Text = "0";
btnStartAdventures.PerformClick();
}
}
and that Timer is :
private void timer1_Tick(object sender, EventArgs e)
{
this.Invoke(new MethodInvoker(delegate { lblTimer.Text = (int.Parse(lblTimer.Text) + 1).ToString(); }));
}
but this timer can not change lblTimer's Text.
how can i fix this problem?
EDIT:
that Thread.Sleep is necessary and i can not remove it.
i want a loop that never ends and those codes are for that.
thanks in advance
As requested;
What do you mean by "a loop that never ends"? A Thread.Sleep on the UI thread (RunWorkerCompleted event executes on the UI thread) will effectively freeze the UI thread, which means that no interaction with the UI thread will be shown.
Comments:
What are you trying to achieve? As far as I can guess, you are doing
some work in a background thread - backgroundWorker5 - (the UI thread
is responsive). When backgroundWorker5 is finished you want to start a
timer and display a counter in a label while the UI is still
responsive (for somebody to stop the timer maybe?). Something like
that? – Mario 3 mins ago edit
yes you are right. i want a loop and it never stops until a user click
cancel button. – MoonLight 1 min ago
So, try something like this:
int time = 0;
private void backgroundWorker5_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnStartAdventures.Text = "Start Adventure";
btnStartAdventures.Enabled = true;
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
return;
}
if (e.Cancelled)
{
lblStatusValueInAdventures.Text = "Cancelled...";
}
else
{
lblStatusValueInAdventures.Text = "Completed";
timer1.Interval = 1000; //<--- Tick each second, you can change this.
timer1.Enabled = true;
timer1.Start();
// MessageBox.Show("start timer");
}
}
private void timer1_Tick(object sender, EventArgs e)
{
lblTimer.Text = (time + 1).ToString();
}
private void button_Cancel_Click(object sender, EventArgs e)
{
//MessageBox.Show("end timer");
timer1.Enabled = false;
timer1.Stop();
lblTimer.Text = "0";
btnStartAdventures.PerformClick();
}
Thread.Sleep
There's your problem.
Never call Thread.Sleep in a UI thread; it will freeze the UI.
Get rid of that, and it will work fine.
You can put the rest of the work in the timer callback.
You can also use C# 5 async to make this much simpler.
You have to refresh item.
lblTimer.Refresh()
and also you could refresh form
frmName.Refresh();
and make thread to sleep 0 milliseconds that gives space for other processes.