views:

279

answers:

4

Hi

I want to write a batch job in c# that runs a task at a random(ish) interval e.g. every hour +/- 20 mins and if no update is needed, then to wait x2 the last time before running again.

What is the best method to do this?

A: 

Consider creating a simple application, and kicking it off with the Windows Task Scheduler. The scheduler gives you a lot of control over when and what runs, and it includes time randomization.

EDIT: missed the '2x' part. In the past, I've built Windows Services to do this:

sleep(1x +/- random(20 minutes))
if nothing to do, sleep(2x +/- random(20 minutes))
Michael Petrotta
A: 

can just create a timer that pops every so often and runs a method.

example:

Timer ProcessTimer = new Timer(new TimerCallback(ProcessRandomTask), null, 0,Timeout.Infinite);


private void ProcessRandomTask(object data)
{
 //Do work

  lock(ProcessTime)
  {
       //change timer
       ProcessTimer.Change(GetNewTime(), Timeout.Infinite);
  }
}
CSharpAtl
+1  A: 

Everyone else's answers are pretty good, but the only thing I can contribute here is something you should not do. Do not make the application a windows service. I've seen it so many times as an answer to similar problems. That is not what windows services are for.

In my book, windows services are applications/programs that hang in the background to facilitate other programs, or do not require user input to operate. It is not to be used as a method of launching your program at time intervals.

Andrew Weir
Well, you're right that it shouldn't be a service unless necessary. Services are a great way to ensure something *always* runs, though, even if the user is logged out, or a machine has been restarted. It sounds like he might want that.
Michael Petrotta
If that is the functionality he wants, then he'll disregard my answer all the same. But it's just an itch I wanted to scratch in public.
Andrew Weir
I will be happy to see this echo out it progress to the screen just so we can tell it working. So will avoid writing a service.
Pbearne
A: 

How about logging the timestamp from the last "unnecessary" run to a database/some permanent location? Then, your first line can say:

LastRunWithoutUpdating = GetLastRunWithoutUpdating() // load from file, or db...
if (LastRunWithoutUpdating - CurrentTime < DelayInterval) {
    SkipThisRun(); // sys.exit() or something
}
ojrac
was trying not to use a db
Pbearne
Unless your program can access the scheduler, you'll need to either have some sort of persistent storage, or the process needs to do its own scheduling (i.e. staying up and Sleep()ing). So, how about writing the "last update" value to a file?
ojrac
possible there may be a couple of other values I will need to store
Pbearne
We use the last modification date on a file for a similar purpose right now. A successful run modifies the file. An unsuccessful run doesn't. The file's age is a measure of the time since the last success. For consistency, we also write a date string or any other useful checkpoint info into the file, but our application only looks at the file's date.
RBerteig
Not sure what to say. If there's multiple values you need to store, then go ahead and do that. C# is good at handling XML.
ojrac