title: C# - How to pause application until timer is finished?
body: <p>I have an application that I need to have wait a specific amount of time, but I also need to be able to cancel the current operation if needed. I have the following code: </p>
  
  <pre><code>private void waitTimer(int days)
  {
      TimeSpan waitTime = TimeSpan.FromDays(days);
      System.Timers.Timer timer = new System.Timers.Timer(waitTime.TotalMilliseconds);   // Wait for some number of milliseconds
      timer.Enabled = true;
      timer.Start();
      timer.Elapsed += new ElapsedEventHandler(OnTimedEvent); // Subscribe to event handler
  
      while (!TimerSettings.TimerFinished &amp;&amp; !quitToken.IsCancellationRequested);  // Loop forever untill timer is finished or operation is cancled. 
  
      timer.Elapsed -= new ElapsedEventHandler(OnTimedEvent); // Unsubscribe
  
      DoWork(); // Do work when timer finishes.......
  }
  </code></pre>
  
  <p>Below is the event handler for the timer finished event: </p>
  
  <pre><code>private void OnTimedEvent(object obj, ElapsedEventArgs e)
  {
      TimerSettings.TimerFinished = true;
  }
  </code></pre>
  
  <p>The while loop just loops infinitely until the timer is finished or until a cancelation request is put in. I want to retain this functionality but I would rather not loop forever while waiting for the timer to finish. My timer can be set to run on an interval of multiple days so it doesn't make sense to loop for so long. </p>
  
  <p>Is there another way of doing this? </p>
  
  <p>I know I could do: </p>
  
  <pre><code>Thread.Sleep(runDuration.TotalMilliseconds);
  </code></pre>
  
  <p>However, this would be blocking and I would not be able to put in a cancelation request. </p>
  
  <p>EDIT: So in order to elaborate on what/why I need to pause here is a more detailed explination of my application. Basically I want to have an application that performs "work" on a regular interval. So based on one of the answers provided below, if I did something like this:</p>
  
  <pre><code>class Program
  {
      // Do something in this method forever on a regular interval 
      //(could be every 5min or maybe every 5days, it's up to the user)
      static void Main(string[] args)
      {
          while(true)
          {
            if(args?.Length &gt; 0)
                waitTimer(args[0]);
            else 
                wiatTimer(TimeSpan.FromDays(1).TotalSeconds); // Default to one day interval
          }             
      }
  
  private void waitTimer(int numIntervals)
  {
      this.ElapsedIntervals = 0;
      this.IntervalsRequired = numIntervals;
      this.timer = new System.Timers.Timer(1000);   // raise the elapsed event every second
      timer.Elapsed += new ElapsedEventHandler(OnTimedEvent); // Subscribe to event handler
      //timer.Enabled = true; timer.Start() does this for you, don't do this
      timer.Start();
      //thats all here
  }
  
   private void OnTimedEvent(object obj, ElapsedEventArgs e)
   {
      this.ElapsedIntervals += 1;
      if(this.CancelRequested)
      {
         this.ElapsedIntervals = 0;
         this.timer.Stop();
         return;
      }
      if(this.ElapsedIntervals &gt;= this.IntervalsRequired)
      {
         this.ElapsedIntervals = 0;
         this.timer.Stop();
         DoWork();   // This is where my work gets done.......
        return;
      }
    }
  }
  </code></pre>
  
  <p>Then my service/console app would start and go into an infinite loop that just sets timers all day long. Previously, I was actually halting execution of any other code at:</p>
  
  <pre><code>while (!TimerSettings.TimerFinished &amp;&amp; !quitToken.IsCancellationRequested);
  </code></pre>
  
  <p>Which at least worked, but as mentioned, can possibly be resource intensive way to pause a thread. Basically what I really need is a way to block my thread untill the timer is up.</p>
  
  <p>EDIT2: This is my final implementation that seems to work for me using a wait handle...</p>
  
  <pre><code>class TimerClass
  {
      /// &lt;summary&gt;
      /// Initialize new timer. To set timer duration,
      /// either set the "IntervalMinutes" app config 
      /// parameter, or pass in the duration timespan.
      /// &lt;/summary&gt;
      /// &lt;param name="time"&gt;&lt;/param&gt;
      internal bool StartTimer(CancellationToken quitToken, TimeSpan? duration = null)
      {
          TimeSpan runDuration = new TimeSpan();
          runDuration = duration == null ? GetTimerSpan() : default(TimeSpan);
  
          if (runDuration != default(TimeSpan))
          {
              WaitTimer(runDuration); // Waits for the runduration to pass
          }
          return true;
      }
  
      /// &lt;summary&gt;
      /// Get duration to run the timer for.
      /// &lt;/summary&gt;
      internal TimeSpan GetTimerSpan()
      {
          TimerSettings.Mode = App.Settings.Mode;
          DateTime scheduledTime = new DateTime();
  
          switch (TimerSettings.Mode)
          {
              case "Daily":
                  scheduledTime = DateTime.ParseExact(App.Settings.ScheduledTime, "HH:mm:ss", CultureInfo.InvariantCulture);
                  if (scheduledTime &gt; DateTime.Now)
                      TimerSettings.TimerInterval = scheduledTime - DateTime.Now;
                  else
                      TimerSettings.TimerInterval = (scheduledTime + TimeSpan.FromDays(1)) - DateTime.Now;
                  break;
              case "Interval":
                  double IntervalMin = double.TryParse(App.Settings.PollingIntervalMinutes, out IntervalMin) ? IntervalMin : 15.00;
                  int IntervalSec = Convert.ToInt32(Math.Round(60 * IntervalMin));
                  TimeSpan RunInterval = new TimeSpan(0, 0, IntervalSec);
                  TimerSettings.TimerInterval = RunInterval;
                  break;
              case "Manual":
                  TimerSettings.TimerInterval = TimeSpan.FromMilliseconds(0);
                  break;
              default:
                  TimerSettings.TimerInterval = (DateTime.Today + TimeSpan.FromDays(1)) - DateTime.Now;
                  break;
          }
          return TimerSettings.TimerInterval;
      }
  
      /// &lt;summary&gt;
      /// Event handler for each timer tick.
      /// &lt;/summary&gt;
      /// &lt;param name="obj"&gt;&lt;/param&gt;
      /// &lt;param name="e"&gt;&lt;/param&gt;
      private void OnTimedEvent(object obj, ElapsedEventArgs e)
      {
          ElapsedIntervals += 1;
          if (CancelRequested.IsCancellationRequested) // If the application was cancled
          {
              ElapsedIntervals = 0;
              timer.Stop();
              WaitHandle.Set();
              return;
          }
          if (ElapsedIntervals &gt;= IntervalsRequired) // If time is up
          {
              ElapsedIntervals = 0;
              timer.Stop();
              WaitHandle.Set();
              return;
          }
      }
  
      /// &lt;summary&gt;
      /// Timer method to wait for a
      /// specified duration to pass. 
      /// &lt;/summary&gt;
      /// &lt;param name="span"&gt;&lt;/param&gt;
      private void WaitTimer(TimeSpan span)
      {
          WaitHandle = new AutoResetEvent(false);
          int tickDuration = 1000;  // Number of milliseconds for each tick
          IntervalsRequired = Convert.ToInt64(span.TotalMilliseconds / (tickDuration &gt; 0 ? tickDuration : 0.01));
          timer = new System.Timers.Timer(tickDuration);          // Raise the elapsed event every tick
          timer.Elapsed += new ElapsedEventHandler(OnTimedEvent); // Subscribe to event handler for when each tick is complete
          timer.Start();           // Start ticking
          WaitHandle.WaitOne();    // Halt the main thread untill span is reached
      }
  
  
      // Timer parameters: 
      private static long ElapsedIntervals { get; set; }
      private static long IntervalsRequired { get; set; }
      private static System.Timers.Timer timer { get; set; }
      private static CancellationToken CancelRequested { get; set; }
      private static string Mode { get; set; }
      private static TimeSpan TimerInterval { get; set; }
      private static EventWaitHandle WaitHandle { get; set; }
  }
  
  internal static class TimerSettings
  {
      internal static string Mode { get; set; }
      internal static TimeSpan TimerInterval { get; set; }
  }
  </code></pre>