1

I want to wait for x hours before executing some code in C#. i thought using a timer would be a good idea. (using thread.sleep does not seem right). But it just does not work. i am using the following code:

static void Main(string[] args)
{
    System.Timers.Timer timer = new System.Timers.Timer();
    timer.Interval = x * 3600000;
    timer.Enabled = true;
    timer.Elapsed += (o, e) => SomeFunction(username);
    timer.AutoReset = true;
    timer.Start();
}

this code supposed to wait for x hours and then execute SomeFunction but when i debug it, the main function ends after timer.start().

do you see any problem here? or can you suggest an alternative besides thread.sleep or await Task.Delay() ?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • `System.Timers.Timer` *normally* uses a background thread to raise the event, so it will start the timer and then move on, it does not block. – Lloyd Jun 17 '15 at 08:46
  • Yes I see a problem there. The call to timer.Start() is asynchronously. This means after the call of timer.Start() execution will continue. This ends your program instantly. What you could do is the most obvious solution to send your main in a endless loop after calling timer.Start() – ckruczek Jun 17 '15 at 08:46
  • What does "does not work" mean? (Also, i'm curious, is this the value you've used for testing or did you try with a lower interval?) – Sayse Jun 17 '15 at 08:47
  • 1
    Of course `Main` exits - there's no code in it after `timer.Start();`. So if your application has nothing else to do, `Thread.Sleep` isn't really any worse than using a timer. That said, it's still a bad idea to use a timer (or `Thread.Sleep`) for this. Why not use e.g. windows task scheduler instead? What are you actually trying to do? Why do you want to run an application that only does something hours after it's launched? – Luaan Jun 17 '15 at 08:47
  • You don't even need a timer for this, record start time, enter an unbound loop and then periodically check time difference and sleep. – Lloyd Jun 17 '15 at 08:48
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Jun 17 '15 at 08:48
  • Yes, i've used lower intervals and still no chance. Thanks for the answers, i've put a [STAThread] before my main function but i think this does not solve the problem. what should i do? – ismail senonder Jun 17 '15 at 08:49
  • Thanks for all the answers, i will look up to it. Well in this situation, i can't use Task Scheduler or a Windows Service because of some circumstances (company network policies, etc etc..). it would be easier if i could :) – ismail senonder Jun 17 '15 at 08:51

3 Answers3

2

As soon as your Main function exits, your process ends, along with any background threads including timers.

You need to keep your main thread alive using Thread.Sleep(), Console.ReadKey() or whatever seems appropriate.

Alternatively, if you don't want to keep your process alive, you can register a scheduled task with Windows to be run in an hour's time, and then end.

Community
  • 1
  • 1
Tim Rogers
  • 21,297
  • 6
  • 52
  • 68
1

There are two problems here. The first is that an executable will exit when all foreground threads are finished running. The only foreground thread is that going through Main() so it will then exit.

The second is that you aren't storing timer anywhere. Even if another thread was keeping the executable going, timer is eligible for garbage collection perhaps as soon as timer.Start() returns and certainly after Main() exits.

using thread.sleep does not seem right

It generally isn't a good idea, but considering that you only have one thread anyway, and considering that you have to have at least one foreground thread in an application, Thread.Sleep seems perfectly reasonable in this particular case. Task.Delay just as much.

More generally, I think I would prefer this to be either a scheduled task or a service. In particular, in cases where I want to wait hours before something is done, I very often want this to survive reboots.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • Not sure about this: _timer is eligible for garbage collection_ I thought it would live while it is running. Good thinking about wanting to survive reboots with a service! – TaW Jun 17 '15 at 14:54
  • @TaW it most certainly is. TImers are a very common use for `GC.KeepAlive()` for precisely this reason. (Note that `GC.KeepAlive()` does nothing except be a method that accepts an object as a parameter and which can't be inlined, which suffices to prevent collection because the compiler can't reuse the stack space until after it's called `KeepAlive()`). – Jon Hanna Jun 17 '15 at 15:15
0

Check out Quartz.Net and this for scheduled tasks.

Community
  • 1
  • 1
Fabjan
  • 13,506
  • 4
  • 25
  • 52