4

I am trying to delay my method by using a timer:

private System.Timers.Timer _delayTimer;

    private void delay()
    {
          _delayTimer = new System.Timers.Timer();
          _delayTimer.Interval = 5000;
          //_delayTimer.Enabled = true;
          _delayTimer.Elapsed += _delayTimer_Elapsed;
          _delayTimer.Start();
          someMethod();
        }
    }

    private void _delayTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        // delay for 5 seconds
    }

When i am get into delay() method i want to start the timer, than i want the 5 seconds delay and only after that i want to execute someMethod() and currently this not happen, after execute delay() the someMethod() executed without 5 seconds delay

Kevin
  • 4,586
  • 23
  • 35
user2214609
  • 4,713
  • 9
  • 34
  • 41

5 Answers5

13

Your current code sets up the timer and then immediately executes someMethod. Instead of this, you need to put the actual method call inside your Elapsed handler:

private void delay()
{
      _delayTimer = new System.Timers.Timer();
      _delayTimer.Interval = 5000;
      //_delayTimer.Enabled = true;
      _delayTimer.Elapsed += _delayTimer_Elapsed;
      _delayTimer.Start();
    }
}

private void _delayTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
      someMethod();
}

And if there's nothing else you intend to do you can simply write this inline:

_delayTimer = new System.Timers.Timer();
_delayTimer.Interval = 5000;
_delayTimer.Elapsed += (o, e) => someMethod();
_delayTimer.Start();
Jon
  • 428,835
  • 81
  • 738
  • 806
  • And if someMethod() received an object as parameter and i am using Timer.Tag property to send this object to _delayTimer_Elapsed, how can i cast this object from _delayTimer_Elapsed ? – user2214609 Oct 15 '13 at 18:46
  • @user2214609: Cast the first argument (`sender` in the long form, `o` in the short form) to `Timer` and access its `Tag`, e.g. `(o, e) => someMethod(((Timer)o).Tag)`. Actually, in the short form you could also directly capture the parameter: `(o, e) => someMethod(_delayTimer.Tag)`. – Jon Oct 15 '13 at 18:47
  • Can i have a short example ? its hard to understand in this way (i am a new developer...), i moved the relevat code into _delayTimer_Elapsed and wants to send to this event MyObject as parameter – user2214609 Oct 15 '13 at 18:52
  • @user2214609: `var timer = (Timer)sender;` and then access `timer.Tag`. – Jon Oct 15 '13 at 18:54
  • I am using System.Timers.Timer _delayTimer and after MyObject object = (Timer)sender got an error: Cannot implicitly convert type 'System.Threading.Timer' to 'my namespace' – user2214609 Oct 15 '13 at 18:58
  • @user2214609: `(System.Threading.Timer)sender`, that should be easy to see. In general you would want to `using System.Threading` at the top of your code file so you don't have to specify the namespace all the time. – Jon Oct 15 '13 at 19:01
6

If you're in .Net4.5(or using BCL.Async pack) you can use Task.Delay

private async void delay()
{
    await Task.Delay(5000);
    someMethod();
}

If you're under .Net4.5

Try the below code. I'll suggest you to use System.Threading.Timer

var timer = new System.Threading.Timer(x => someMethod(), null, 5000, System.Threading.Timeout.Infinite);\

Don't forget when you use Threading.Timer someMethod will be invoked in ThreadPool thread, If you're accessing UI you need to marshal the call to UI thread.

T.Todua
  • 53,146
  • 19
  • 236
  • 237
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
4

If you want the current thread to pause for five seconds, then call Thread.Sleep. For example:

Thread.Sleep(TimeSpan.FromSeconds(5));
DoSomething();

Use a timer if you want something to happen five seconds from now, while you're doing something else. When the timer elapses, the action will be executed on a thread pool thread.

Also, if you only want the timer to execute one time (rather than once every five seconds), be sure to set AutoReset to false.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
2

You need to call someMethod in the timer's Elapsed handler:

private void delay()
{
      _delayTimer = new System.Timers.Timer();
      _delayTimer.Interval = 5000;
      _delayTimer.AutoReset = false; //so that it only calls the method once
      _delayTimer.Elapsed += (s,args) => someMethod();
      _delayTimer.Start();
}

You could also use Task.Delay instead:

private void delay()
{
    Task.Delay(5000)
    .ContinueWith(t => someMethod());
}
Servy
  • 202,030
  • 26
  • 332
  • 449
  • 2
    Might be worth noting that if `someMethod` accesses any UI components then an illegal cross thread call will occur. In order to resolve this you could pass the result of `TaskScheduler.FromCurrentSynchronizationContext()` as the second argument to the `ContinueWith` method. – User 12345678 Oct 15 '13 at 18:42
1
System.Threading.Tasks.Task.Factory.StartNew(() =>
            {
                System.Threading.Thread.Sleep(5000);
                /*
                 * Here Yopur code to do some method :D
                 * */
            });
kazem
  • 3,671
  • 1
  • 22
  • 21