2

I have been searching for information and couldn't find any. My question is how to start DispatcherTimer from N seconds or minutes or hours. I mean currently it starts from 00:00:00 (also displayed in CurrentTime Label) but if I would like to start it from 00:00:30 (also display in CurrentTime Label), what should be differently?

To clarify it more... When I start an application I execute StartWorkingTimeTodayTimer(). Then I have a Label (CurrentTime) that is starting to show time of application runtime. Currently it starts from 00:00:00. I would like to display for example 00:00:30 at Start and then tick by one second as it is right now... so 00:00:30 -> 00:00:31 -> 00:00:32 -> 00:00:33 -> 00:00:34 ->

I have tried to play with:

DateTime x30SecsLater = StartTimeWholeDay.AddSeconds(30);

without success.

Current code:

private static DateTime StartTimeWholeDay;
private DispatcherTimer _dailyTimer;

public void StartWorkingTimeTodayTimer()
{
    StartTimeWholeDay = DateTime.Now;
    DateTime x30SecsLater = StartTimeWholeDay.AddSeconds(30);

    _dailyTimer = new DispatcherTimer(DispatcherPriority.Render);
    _dailyTimer.Interval = TimeSpan.FromSeconds(1);
    _dailyTimer.Tick += (sender, args) =>
    {
        CurrentTime = (DateTime.Now - StartTimeWholeDay).ToString(@"hh\:mm\:ss"); // DateTime.Now.ToLongTimeString()
    };
    _dailyTimer.Start();
} 

EDIT:

I have tried already:

public void StartWorkingTimeTodayTimer()
{
    StartTimeWholeDay = DateTime.Now;
    DateTime x30SecsLater = StartTimeWholeDay.AddSeconds(30);

    _dailyTimer = new DispatcherTimer(DispatcherPriority.Render);
    _dailyTimer.Interval = TimeSpan.FromSeconds(1);
    _dailyTimer.Tick += (sender, args) =>
    {
        CurrentTime = (DateTime.Now - x30SecsLater).ToString(@"hh\:mm\:ss"); // DateTime.Now.ToLongTimeString()
    };
    _dailyTimer.Start();
}

but it calculates backwards...

enter image description here

It should go the other way 00:00:30 -> 00:00:31 -> 00:00:32 -> 00:00:33 -> 00:00:34 ->

10101
  • 2,232
  • 3
  • 26
  • 66
  • how about using a `Task.Delay` before the timer start? – JHBonarius Nov 28 '20 at 13:52
  • I was thinking about this some more, but the question is not fully clear: do you really want the timer to start with a 30 seconds delay, or do you want `CurrentTime` to have an offset of 30 seconds? – JHBonarius Nov 28 '20 at 14:05
  • I don't want to start with delay. I just want to start counting from certain time. Not from zero (00:00:00) as it is now but let's say from (00:00:30 or 00:03:00 or 03:00:50). Not in sense of timer should wait or start at certain time, just be able to specify time (number) from where to start counting. This should be something very simple, but I just can't figure how. – 10101 Nov 28 '20 at 14:19
  • Well it seems you were already halfway there... Why didn't you try `CurrentTime = (DateTime.Now - x30SecsLater).`... that would start at "-30 seconds"... gives a hint. – JHBonarius Nov 28 '20 at 14:20
  • Please see my edited question – 10101 Nov 28 '20 at 14:28
  • @hatman please check this: https://codereview.stackexchange.com/questions/13354/delayed-dispatcher-invoke – Hasan Fathi Nov 28 '20 at 14:31
  • If it counts backwards, the minus operation is reversed: `(x30SecsLater - DateTime.Now)`. And you should use 'x30Secs**Earlier**'. – JHBonarius Nov 28 '20 at 14:35
  • @hatman and try this: https://stackoverflow.com/questions/3740822/delayed-dispatch-invoke – Hasan Fathi Nov 28 '20 at 14:35
  • @JHBonarius `CurrentTime = (x30MinsLater - DateTime.Now).ToString(@"hh\:mm\:ss");` goes backwards as well – 10101 Nov 28 '20 at 14:36
  • Sorry, I'm trying to reproduce your issue in the mean time, but having a hard time getting WindowsBase.dll loaded in .NET 5 – JHBonarius Nov 28 '20 at 14:42
  • I think I get the issue: your custom `ToString` is not showing negative time... just wait and it will count up again... I'll form an answer soon. – JHBonarius Nov 28 '20 at 14:43
  • I have dropped it to GitHub https://github.com/vadimffe/DispatherTimer – 10101 Nov 28 '20 at 15:06

1 Answers1

2

After struggeling a LONG time to get WPF running with a console (in .NET 5) ...I failed, so I'll give the answer using System.Timers. But you get the idea.

using System;
using System.Timers;

namespace TimerExample
{
    class Program
    {
        private static DateTime _startTime;

        private static void OnTimedEvent(object source, ElapsedEventArgs eea)
        {
            Console.WriteLine((eea.SignalTime - _startTime)
                .Add(TimeSpan.FromSeconds(29)) // 29, because the first trigger happens 1 sec after start
                .ToString(@"hh\:mm\:ss"));
        }

        static void Main(string[] args)
        {
            _startTime = DateTime.Now;
            var timer = new Timer
            {
                Interval = 1000, // msec
                AutoReset = true,
            };
            timer.Elapsed += OnTimedEvent;
            timer.Start();

            Console.WriteLine("Press any key to stop");
            Console.ReadKey();
        }
    }
}

OR

using System;
using System.Timers;

namespace TimerExample
{
    class Program
    {
        private static DateTime _startTime;

        private static void OnTimedEvent(object source, ElapsedEventArgs eea)
        {
            Console.WriteLine((eea.SignalTime - _startTime)
                .ToString(@"hh\:mm\:ss"));
        }

        static void Main(string[] args)
        {
            _startTime = DateTime.Now.AddSeconds(-29); // again 29 instead of 30
            var timer = new Timer
            {
                Interval = 1000, // msec
                AutoReset = true,
            };
            timer.Elapsed += OnTimedEvent;
            timer.Start();

            Console.WriteLine("Press any key to stop");
            Console.ReadKey();
        }
    }
}
JHBonarius
  • 10,824
  • 3
  • 22
  • 41