Minimalist countdown timer with C# I'm looking to add a module to one of my utility classes that functions as a countdown timer for tools that execute tasks after a certain amount of time. The code below is what I have working for PoC, but when I went to make this and check out existing examples, none really seemed this slim/simple without going all-out on lambdas, so I'm worried that I'm doing something wrong, or at the very least very inefficiently.

The time-range expected for the tool will be from 200 milliseconds to a few hours.

using System;

namespace CountdownTimer
{
    class Program
    {
        static int Main(string[] args)
        {
            int aDelay = 2000;    
            CountDown(aDelay);    
            return 0;
        }

        static void CountDown(int delayInMilliseconds)
        {
            bool finishedCountdown = false;
            DateTime initialTime = DateTime.UtcNow;

            while (!finishedCountdown)
            {
                DateTime timeNow = DateTime.UtcNow;    
                TimeSpan timeDifference = timeNow - initialTime;

                if (timeDifference.TotalMilliseconds &gt;= delayInMilliseconds)
                {
                    finishedCountdown = true;
                }
            }
        }
    }
}


I also have this alternative when I was futzing around with async, which I'm kind of new to in C#

using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace CountdownTimer
{
    class Program
    {
        static int Main(string[] args)
        {
            var result = CountDownTimer(5000);
            Console.ReadKey(true);

            return 0;
        }

        async static Task CountDownTimer(int delay)
        {
            Task myDelay = AsyncDelay(delay);    
            await myDelay;
        }

        async static Task AsyncDelay(int delay)
        {
            await Task.Delay(TimeSpan.FromMilliseconds(delay));
            Console.WriteLine("Done");
        }
    }
}


I think they're both pretty easy to understand, but my uncertainty with C#'s async for the second solution and the CPU cycles being used for the first worry me...

side note: Any version of .NET is available for use
Without more context it's really hard to give you a particularly helpful answer but I can suggest a couple of things.

Your first option is about as bad as it gets, it will thrash CPU because as far as the CPU is concerned that while loop is important work - it doesn't know you're just calculating a time over and over again.

Your second option isn't bad but you should accept an action to run after the delay otherwise it won't be very flexible. You should also use TimeSpan to represent an interval - an int can mean many things, a TimeSpan represents the information unambiguously.

For the sake of completeness, for this trivial example I think it's clearer without the async and await but that's just personal preference.

public static Task DoActionAfter(TimeSpan delay, Action action)
{
    return Task.Delay(delay).ContinueWith(_ =&gt; action());
}


As you're returning a Task your code can synchronously wait using .Wait() (not great) or await the result. If it doesn't need the result straight away it can just store the task and check its status later.

If you want to be able to cancel your action you should feed a CancellationToken into the method (and the delay).

Update

To actually use the method:

using System;
using System.Threading.Tasks;

namespace CountdownTimer
{
    class Program
    {
        public static void Main()
        {
            var delayInterval = TimeSpan.FromMilliseconds(5000);
            var runningTask = DoActionAfter(
                delayInterval,
                () =&gt; Console.WriteLine("Done"));

            // if you want your main method to wait for the action
            // runningTask.Wait()

            Console.ReadKey();
        }

        public static Task DoActionAfter(TimeSpan delay, Action action)
        {
            return Task.Delay(delay).ContinueWith(_ =&gt; action());
        }
    }
}