views:

79

answers:

4

I have a table of schedule items, they may be scheduled for the same time. I'm wondering how to have them all execute at the correct time when:

The problem I see is that executing one scheduled item (like a scheduled twitter post) requires an API request which may take up to a second or two - probably longer. If I execute them sequentially + there are too many scheduled items at the same time, the time they get executed at could be after the scheduled time.

How would I go about building this "scheduling" system that avoids these problems? Any tips, advice?

Thanks!

+4  A: 

I would use a Windows service to accomplish this. Then each of the items should be scheduled asynchronously using the BackgroundWorker process. This would allow all of the scheduled processes to be launched rapidly asynchronously so they don't collide and aren't depending on the previous one finishing before kicking off.

Joel Etherton
I agree, it's better to let the framework handle the threads.
Jason Rowe
So, would you say this is a good process: 1. Go to database, get scheduled items for this minute2. Iterate through scheduled items, "launching" each one as a backgroundworker process3. Sleep until next minute4. Repeat?And have this run as a windows service?
rksprst
I would. I would also recommend create a "state manager" kind of class to keep track of it all. Each BackgroundWorker would be able to report back on its progress independently. So you'd be able to track if there were any independent failures, messages, etc.
Joel Etherton
+1  A: 

Unless you take steps to take advantage of the asynchronous APIs that exist for all IO operations, your only approach is to use many threads. Consider the .net ThreadPool as this can increase the number of threads when too many work items are queued. There will be a limit here, as the ThreadPool spins up extra threads relatively slowly. Under sustained overload, your system will groan. Like I said, the best way to approach this is with asynchronous IO.

spender
+3  A: 

You might want to consider Quartz.NET. Gives you much flexibility in terms of scheduling and task execution.

o.k.w
A: 

You can put the tasks in threads when you get want them to run:

public abstract class MyTask {
    public abstract void DoWork();
}


// ...

public void SomeTaskStarter()
{
    MyTask task = SomeFactoryMethodToCreateATaskInstance();

    new Thread(new ThreadStart(task.DoWork)).Start();
}

MyTask is an abstract class that represents a task to do and it defines a method, DoWork() that will do what you want. SomeFactoryMethodToCreateATaskInstance() will construct a concrete instance of a task and all you need to do is write DoWork() to do what you need to do:

public class Twitterer : MyTask
{
    private string _tweet;
    public Twitterer(string tweet)
    {
        _tweet = tweet;
    }
    public override DoWork()
    {
        TwitterApi api = new TwitterApi(); // whatever
        api.PostTweet(tweet);
    }
}

You will most assuredly want some kind of action of task completion. Whatever you do, the task completion routine should be threadsafe, and should probably be called via BeginInvoke()/EndInvoke() if you need to do any UI-ish work.

SomeTaskStarter() is best called from a windows service, and will most likely contain an argument with information about what task should be started, etc.

plinth