Feb 2, 2011 at 3:08 PM

Thanks for creating this project. Nice idea and execution. This is great for someone like me who doesn't need Quartz.Net functionalities but still want a flexible enough scheduler.

Just wondering if anymore updates are forthcoming? Or do you think it's mature enough to stop any activity on it...

Feb 3, 2011 at 8:02 PM

I'm curious to hear what features you think are missing or whatever suggestions you may have. This library is functional and stable, so I don't plan on adding any new features immediately. Feel free to make suggestions or fork the source and submit a pull request!

Feb 3, 2011 at 8:13 PM

I think having a way to dynamically remove or update a task in the current list of scheduled tasks would be very helpful. Right now all the tasks are loaded once at application start and that's it. You either zap the whole thing and start from scratch if you want some task removed or updated. If i decide to add this feature, is there a recommend way to do it? I'd like to be able to contribute back if it's acceptable.

Feb 4, 2011 at 3:28 PM

That's a great suggestion, something I considered once but never had a need for so it fell to the back-burner. I'd love for you to take a crack at it. The preferred way to contribute is to create a fork here on CodePlex ( If you're not familiar with Mercurial, is a great resource. Once you've pushed your code, you can submit a pull request to me, which allows me to merge in your changes.

The scheduler actually has three definitions for a schedule: two user-defined classes (the fluent class, the XML configuration classes) and a runtime class that is used for evaluation every second. The runtime class is optimized for performance with bitwise arithmetic (ScheduleDefinition.Evaluate). 

User-schedules are converted to the runtime schedule in TaskEvaluationPump.Initialize or InitializeFromConfig. Those methods create _schedule = new List<ScheduleDefinition>() (the runtime class) and add the user-defined schedules. Adding tasks at runtime is straightforward: you could add a method on TaskEvaluationPump that resembles Initialize, and adds new items to _schedule. As soon as they're added, they'll immediately get picked up by TaskEvaluationPump.Evaluate. NOTE you'll need to lock (please use around adding and reading from _schedule since adding while enumerating will throw an exception. Once you've added logic to the guts, you'll need to expose it as a static method on SchedulerRuntime. Similar to Initialize(), there could be a RuntimeAdd() method.

Removing at runtime is less intuitive, since there is no "key" to search for. If you pull up Configuration.At or ScheduleDefinition, you'll see commented out Name properties, which was the key at one point. If you wanted runtime deletion of schedules, _schedules couldn't bee a List<ScheduleDefinition>(), instead it would need to be a Dictionary<string,ScheduleDefinition>(), with the Name as the key. It could be made an optional property (default to Guid.NewGuid().ToString()) so that users only need specify it if they think they might delete or modify it later.

Once you wire up schedules to have a key, you are already familiar with the guts of TaskEvaluationPump and the user API SchedulerRuntime; just add a delete method that looks for the key and removes it from _schedule.

Hope you decide to give it a try! 


Feb 5, 2011 at 5:16 PM
Edited Feb 5, 2011 at 5:22 PM

Thank you for the very clear guidance. Just trying to say here what i plan on doing to confirm my understanding what you said above.

I'm thinking of giving both "Schedule" and "At" a public Name that will return Guid.NewGuid() if their private _name property is null. And then ScheduleDefinition will get that Name when Initialize() or InitializeFromConfig() is called inside TaskEvaluatorPump. _schedule will be converted to Dictionary<> and methods exposed in SchedulerRuntime to add/update/delete associated schedules (lock will be used). Tasks are added/updated/deleted by virtue of belonging to their parent's user-schedule objects and won't have their own static method to manipulate individual task. Maybe if there's a real need in the future, task can get their own methods but i don't want to muddle up the picture just yet...

Does that sound like a workable plan?



Feb 5, 2011 at 9:35 PM

Sounds like you've got it, Thinh! I see you created a fork; just let me know when you're ready for a code review & integration, or if you hit any stumbling blocks. 

Feb 7, 2011 at 2:49 AM

Travis, thanks for the integration. I like those changes you made. I ran my test and found a small bug. Should the line below read ExitReadLock() instead of ExitWriteLock() ?

public IEnumerable<string> ListScheduleName()
    var names = _schedule.Keys.ToArray();
    _scheduleLock.ExitWriteLock();    <==== ExitReadLock() ???

    return names;

Feb 7, 2011 at 2:36 PM

Good catch. I'll be pushing another revision shortly that fixes that.

Feb 7, 2011 at 6:33 PM

It's all good now!