6

I want to run a function periodically every 1 second, so after 10 seconds it is executed 10 times. The simplest approach is using a loop like this :

while(true)
{
Thread.Sleep(1000);
function();
}

But the main problem with this approach is that it will not provide any periodic guarantees. I mean if it takes 0.1 seconds to run function() the executions time of the function will be like this : 0, 1.1 , 2.2, 3.3, 4.4 , ...

As I remember, in real time language ADA we have a function sleep-until(#time). Now I'm looking for an alternative in C#.

Any sample code will be appreicated.

user1654052
  • 85
  • 2
  • 7
  • 2
    Sleep in smaller inverals and check if a whole second has passed before you execute your code. – VVS Oct 11 '12 at 07:50
  • What do you want to happen if function() takes more than 1 second to execute? – Dylan Smith Oct 11 '12 at 07:51
  • c# is not a real time language. its not even guarranted the thread will execute exactly after 1 second, as there might be other threads / processes. if you need to be that precise, maybe you should use some other tools? – YavgenyP Oct 11 '12 at 07:52
  • I assume it will not take longer than 1 sec.but if multi threading is possible I like to run them in parallel. I know c# is not a realtime language but interested to know if we can simulate realtime behaviour in some way. – user1654052 Oct 11 '12 at 07:53
  • 1
    http://stackoverflow.com/questions/4409558/c-sharp-timer-run-every-5th-minute – Mudassir Hasan Oct 11 '12 at 07:53
  • @user1654052 can you elaborate on what you're trying to achieve? threads real level of parallelism is limited to number of cores your pc has. anythign above this pays the price of OS's context switching. both the answers provided here so far wont really work the way you expect it, and you will always have some level of overhead and time wasted. – YavgenyP Oct 11 '12 at 07:58
  • why do you want to run the function every 1 second? Spawning a new thread every one second or queuing the task to thread pool will cause additional threads to be created. If the function can be run truly concurrently then you may want to utilize Task Parallel Library. The TPL will efficiently utilize the multi-core infrastructure. – jags Oct 11 '12 at 08:02
  • @YavgenyP Since c# is not designed to be a realtime language I think there is no other way to achieve what I'm looking for. Do you have any other suggestion ? @ jags I think my thread will finish job before the deadline, so I think there is no problem here. – user1654052 Oct 11 '12 at 09:35
  • @user1654052 , i just dont think that its a big price to pay, in most of the cases. if its very important for you to be as precise as possible, probably using a smaller intervals is a better idea. as of using timer - it still wont be 100% precise.. – YavgenyP Oct 11 '12 at 09:47

3 Answers3

7
System.Threading.Timer timer = new System.Threading.Timer(ThreadFunc, null, 0, 1000);

private static void ThreadFunc(object state)
{
    //Do work in here.
}

See MSDN for more info.

nick_w
  • 14,758
  • 3
  • 51
  • 71
3

You can use Stopwatch to measure the time. I would also use a For-Loop instead.

var sw = new System.Diagnostics.Stopwatch();
var timeForOne = TimeSpan.FromSeconds(1);
var count = 10;
for(int i = 0; i < count; i++)
{
    sw.Restart();
    function();
    sw.Stop();
    int rest = (timeForOne - sw.Elapsed).Milliseconds;
    if (rest > 0)
        System.Threading.Thread.Sleep(rest);
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Great, but I still think the last if block, the calculation of rest and sleep function call consume sometime and cannot see any advantages over the previous one !! It is an alternative but the other one looks simpler :) – user1654052 Oct 11 '12 at 09:40
  • @user1654052: Actually it is unquantifiable what `TimeSpan.Subtract`+ `if (rest > 0)` consumes, it is absolutely negligible and less than 1 millisecond. – Tim Schmelter Oct 11 '12 at 09:44
  • its not just that. take a look carefully.[ sw.stop ; int rest = blah ; if (rest>0) ] all executed without considering its time and task swiches :) I know it looks negligible but if it is going be run for one years you can not guarantee that the function is executed every one second. that is why I don't think it is an acceptable answer – user1654052 Oct 11 '12 at 09:55
  • 1
    @user1654052: You can omit the `sw.Stop();` because it will be used only once later(`sw.Elapsed`). Anyway, all three lines will consume far less than a millisecond because they are simple arithmetic. However, you are right that you need compensation for rounding issues etc. if it's running for a long time and you need high precision. – Tim Schmelter Oct 11 '12 at 10:01
1

To invoke something after specific interval of time you should use Timer class. Here is the Tutorial

taher chhabrawala
  • 4,110
  • 4
  • 35
  • 51