How to make a countdown Timer continue even when Winform is closed?

Uyen Nguyen 21 Reputation points
2022-05-11T01:28:51.26+00:00

Hello. I'm new to windows form so I don't really understand how things work. Recently, I try to make a countdown timer that counts from a certain time to 0. But when the form is closed, everything is like "reset" and I don't want that. What I want is, for example, countdown time is 5 mins -> close form -> open form after 3 mins -> countdown time is 2 mins left. I wonder if you guys can share any ideas that will make it works and are simple so I can understand . Thanks in advance!

Developer technologies Windows Forms
Developer technologies C#
0 comments No comments
{count} votes

Accepted answer
  1. Jack J Jun 25,296 Reputation points
    2022-05-11T07:43:56.063+00:00

    @Uyen Nguyen , Welcome to Microsoft Q&A, Based on your description, you want to make a countdown timer and hope that it will contine when the form is closed.

    I make some steps and code example. You could check if it works for you.

    First, I make a countdown Timer from the answer.

    Second, I add the following settings in the winform.

    200800-image.png

    Third, I used FormClosing event to save some information to the settings.

      private void Form1_FormClosing(object sender, FormClosingEventArgs e)  
            {  
                if(timer.IsRunnign)  
                {  
                    Properties.Settings.Default.lefttime = label1.Text;  
                    Properties.Settings.Default.Isrunning = true;  
                    Properties.Settings.Default.closedtime=DateTime.Now;  
                    Properties.Settings.Default.Save();  
                }  
            }  
      
     Fourth, I used Form1_Load event to read the information.  
      
      private void Form1_Load(object sender, EventArgs e)  
            {  
                if (Properties.Settings.Default.Isrunning== true)  
                {  
                    string lefttime = Properties.Settings.Default.lefttime;  
                    TimeSpan time1=TimeSpan.ParseExact(lefttime, @"mm\:ss", CultureInfo.CurrentCulture);  
                    DateTime closedtime = Properties.Settings.Default.closedtime;  
                    TimeSpan passedtime = DateTime.Now - closedtime;  
                    var t = time1.Subtract(passedtime);  
                    label1.Text=t.ToString(@"mm\:ss");  
                    timer.SetTime(t.Minutes, t.Seconds);  
                    timer.Start();  
                    timer.TimeChanged += () => { label1.Text = timer.TimeLeftStr; };  
      
                    // show messageBox on timer = 00:00.000  
                    timer.CountDownFinished += () => { timer.Stop(); MessageBox.Show("Timer finished the work!"); };  
      
                    //timer step. By default is 1 second  
                    timer.StepMs = 1; // for nice milliseconds time switch  
                }  
                else  
                {  
                    //set to 5 mins  
                    timer.SetTime(5, 0);  
      
                    //update label text  
                    timer.TimeChanged += () => { label1.Text = timer.TimeLeftStr; };  
      
                    // show messageBox on timer = 00:00.000  
                    timer.CountDownFinished += () => { timer.Stop(); MessageBox.Show("Timer finished the work!"); };  
      
                    //timer step. By default is 1 second  
                    timer.StepMs = 1; // for nice milliseconds time switch  
                }  
                 
            }  
    

    Finally, Please set the properties when we click the stop button.

    Completed code:

     public partial class Form1 : Form  
        {  
            public Form1()  
            {  
                InitializeComponent();  
            }  
            CountDownTimer timer = new CountDownTimer();  
            private void Form1_Load(object sender, EventArgs e)  
            {  
                if (Properties.Settings.Default.Isrunning== true)  
                {  
                    string lefttime = Properties.Settings.Default.lefttime;  
                    TimeSpan time1=TimeSpan.ParseExact(lefttime, @"mm\:ss", CultureInfo.CurrentCulture);  
                    DateTime closedtime = Properties.Settings.Default.closedtime;  
                    TimeSpan passedtime = DateTime.Now - closedtime;  
                    var t = time1.Subtract(passedtime);  
                    label1.Text=t.ToString(@"mm\:ss");  
                    timer.SetTime(t.Minutes, t.Seconds);  
                    timer.Start();  
                    timer.TimeChanged += () => { label1.Text = timer.TimeLeftStr; };  
      
                    // show messageBox on timer = 00:00.000  
                    timer.CountDownFinished += () => { timer.Stop(); MessageBox.Show("Timer finished the work!"); };  
      
                    //timer step. By default is 1 second  
                    timer.StepMs = 1; // for nice milliseconds time switch  
                }  
                else  
                {  
                    //set to 5 mins  
                    timer.SetTime(5, 0);  
      
                    //update label text  
                    timer.TimeChanged += () => { label1.Text = timer.TimeLeftStr; };  
      
                    // show messageBox on timer = 00:00.000  
                    timer.CountDownFinished += () => { timer.Stop(); MessageBox.Show("Timer finished the work!"); };  
      
                    //timer step. By default is 1 second  
                    timer.StepMs = 1; // for nice milliseconds time switch  
                    Console.WriteLine(Properties.Settings.Default.lefttime);  
                }  
                 
            }  
      
            private void button1_Click(object sender, EventArgs e)  
            {  
                timer.Start();  
            }  
      
            private void button2_Click(object sender, EventArgs e)  
            {  
                timer.Pause();  
            }  
      
            private void button3_Click(object sender, EventArgs e)  
            {  
                timer.Stop();  
                timer.Dispose();  
                Properties.Settings.Default.lefttime = "";  
                Properties.Settings.Default.Isrunning = false;  
                Properties.Settings.Default.closedtime = DateTime.Now;  
                Properties.Settings.Default.Save();  
            }  
      
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)  
            {  
                if(timer.IsRunnign)  
                {  
                    Properties.Settings.Default.lefttime = label1.Text;  
                    Properties.Settings.Default.Isrunning = true;  
                    Properties.Settings.Default.closedtime=DateTime.Now;  
                    Properties.Settings.Default.Save();  
                }  
            }  
        }  
        public class CountDownTimer : IDisposable  
        {  
            public Stopwatch _stpWatch = new Stopwatch();  
      
            public Action TimeChanged;  
            public Action CountDownFinished;  
      
            public bool IsRunnign => timer.Enabled;  
      
            public int StepMs  
            {  
                get => timer.Interval;  
                set => timer.Interval = value;  
            }  
      
            private Timer timer = new Timer();  
      
            private TimeSpan _max = TimeSpan.FromMilliseconds(30000);  
      
            public TimeSpan TimeLeft => (_max.TotalMilliseconds - _stpWatch.ElapsedMilliseconds) > 0 ? TimeSpan.FromMilliseconds(_max.TotalMilliseconds - _stpWatch.ElapsedMilliseconds) : TimeSpan.FromMilliseconds(0);  
      
            private bool _mustStop => (_max.TotalMilliseconds - _stpWatch.ElapsedMilliseconds) < 0;  
      
            public string TimeLeftStr => TimeLeft.ToString(@"mm\:ss");  
      
            public string TimeLeftMsStr => TimeLeft.ToString(@"mm\:ss\.fff");  
      
            private void TimerTick(object sender, EventArgs e)  
            {  
                TimeChanged?.Invoke();  
      
                if (_mustStop)  
                {  
                    CountDownFinished?.Invoke();  
                    _stpWatch.Stop();  
                    timer.Enabled = false;  
                }  
            }  
      
            public CountDownTimer(int min, int sec)  
            {  
                SetTime(min, sec);  
                Init();  
            }  
      
            public CountDownTimer(TimeSpan ts)  
            {  
                SetTime(ts);  
                Init();  
            }  
      
            public CountDownTimer()  
            {  
                Init();  
            }  
      
            private void Init()  
            {  
                StepMs = 1000;  
                timer.Tick += new EventHandler(TimerTick);  
            }  
      
            public void SetTime(TimeSpan ts)  
            {  
                _max = ts;  
                TimeChanged?.Invoke();  
            }  
      
            public void SetTime(int min, int sec = 0) => SetTime(TimeSpan.FromSeconds(min * 60 + sec));  
      
            public void Start()  
            {  
                timer.Start();  
                _stpWatch.Start();  
            }  
      
            public void Pause()  
            {  
                timer.Stop();  
                _stpWatch.Stop();  
            }  
      
            public void Stop()  
            {  
                Reset();  
                Pause();  
            }  
      
            public void Reset()  
            {  
                _stpWatch.Reset();  
            }  
      
            public void Restart()  
            {  
                _stpWatch.Reset();  
                timer.Start();  
            }  
      
            public void Dispose() => timer.Dispose();  
        }  
    

    Tested result:

    200921-3.gif

    Hope this could help you.

    Best Regards,
    Jack


    If the answer is the right solution, please click "Accept Answer" and upvote it.If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.