Scenario:I wanted a task scheduler/doer that enables my application to schedule some tasks to be executed in a specified time but in the same order they were scheduled in or depending on their priorities (DataFlow like).  I also wanted it to enable the usage of C# 5 Async/Await functionality so I looked up over the Internet and didn't found something the truly fit my needs so I decided to implement one... a simple yet advanced (in my opinion) task scheduler that exactly achieved what I want. However, I want to improve it by hearing your opinions about it.Implementation:1) Scheduler Classusing System;using System.Collections.Generic;using System.Linq;using System.Threading;using System.Threading.Tasks;namespace ATScheduler{    public abstract class Scheduler    {        #region Fields        private readonly TimeSpan _baseInterval;        private readonly TimeSpan _executionTimeOut;        private readonly List<IJob> _jobs;        private readonly object _sync;        private readonly Timer _timer;        private bool _paused;        #endregion        #region Constructors        protected Scheduler()        {            _jobs = new List<IJob>();            _sync = new object();            _baseInterval = TimeSpan.FromMilliseconds(12000);            _executionTimeOut = TimeSpan.FromMilliseconds(30000);            _timer = new Timer(ProcessJobs, null, Timeout.Infinite, Timeout.Infinite);        }        #endregion        #region Methods        public abstract Task JobTriggered(IJob job);        public abstract Task JobException(IJob job, Exception exception);        private void ProcessJobs(object state)        {            lock (_sync) {                IJob[] jobsToExecute = (from jobs in _jobs                    where jobs.StartTime <= DateTimeOffset.Now && jobs.Enabled                    orderby jobs.Priority                    select jobs).ToArray();                if (jobsToExecute.Any()) {                    foreach (IJob job in jobsToExecute) {                        try {                            JobTriggered(job).Wait(_executionTimeOut);                        }                        catch (AggregateException exception) {                            JobException(job, exception).Wait(_executionTimeOut);                        }                        if (job.Repeat) {                            job.StartTime = DateTimeOffset.Now.Add(job.Interval);                        }                        else {                            _jobs.Remove(job);                        }                        if (_jobs.Count <= 0 || _paused)                        {                            _timer.Change(Timeout.Infinite, Timeout.Infinite);                        }                        else                        {                            _jobs.Sort((first, second) => first.StartTime.CompareTo(second.StartTime));                            TimeSpan delay = _jobs[0].StartTime.Subtract(DateTimeOffset.Now);                            long dueTime = Math.Min(Math.Max(100, (long)delay.TotalMilliseconds), (int)_baseInterval.TotalMilliseconds);                            _timer.Change((int)dueTime, Timeout.Infinite);                        }                    }                }            }        }        public void PauseScheduler()        {            if (!_paused) {                _paused = !_paused;            }        }        public void ResumeScheduler()        {            if (_paused) {                _paused = !_paused;            }        }        public void AddJob(IJob job)        {            _jobs.Add(job);            _jobs.Sort((first, second) => first.StartTime.CompareTo(second.StartTime));            TimeSpan delay = _jobs[0].StartTime.Subtract(DateTimeOffset.Now);            long dueTime = Math.Min(Math.Max(100, (long)delay.TotalMilliseconds), (int)_baseInterval.TotalMilliseconds);            _timer.Change((int)dueTime, Timeout.Infinite);        }        public Task<T> AddJob<T>(IJob<T> job)        {            if (job.Repeat) {                throw new Exception(Repeatable jobs can't be awaited!);            }            _jobs.Add(job);            _jobs.Sort((first, second) => first.StartTime.CompareTo(second.StartTime));            TimeSpan delay = _jobs[0].StartTime.Subtract(DateTimeOffset.Now);            long dueTime = Math.Min(Math.Max(100, (long)delay.TotalMilliseconds), (int)_baseInterval.TotalMilliseconds);            _timer.Change((int)dueTime, Timeout.Infinite);            return job.TaskCompletionSource.Task;        }        public void RemoveJob(IJob job)        {            _jobs.RemoveAll(x => x.Equals(job));        }        #endregion    }}2) IJob Interfaceusing System;using System.Threading.Tasks;namespace ATScheduler{    public interface IJob    {        TimeSpan Interval { get; }        DateTimeOffset StartTime { get; set; }        int Priority { get; }        bool Repeat { get; }        bool Enabled { get; set; }    }    public interface IJob<T> : IJob    {        TaskCompletionSource<T> TaskCompletionSource { get; set; }        void Return(T result);    }}3) How to use:using System;using System.Threading.Tasks;using ATScheduler;namespace AdvancedScheduler{    internal class Program : Scheduler    {        private static void Main()        {            Console.WriteLine(- Advanced yet simple Flow Task Scheduler!);            Console.WriteLine();            new Program().DoApplication();            Console.Read();        }        private async void DoApplication()        {            AddJob(new SimpleJob());            AddJob(new SimpleUndefinedJob());            Console.WriteLine(Awaitable job returned: {0}, await AddJob(new SimpleAwaitableJob()));        }        public override async Task JobTriggered(IJob job)        {            if (job is SimpleJob) {                await Task.Delay(1); //or time consumable task.                Console.WriteLine(Simple Job executed for {0} times, ((SimpleJob)job).ExecutionCounter);                ((SimpleJob)job).ExecutionCounter++;            }            else if (job is SimpleAwaitableJob) {                ((SimpleAwaitableJob) job).Return(5);            }            else {                throw new Exception(Undefined Job!);            }        }        public override async Task JobException(IJob job, Exception exception)        {            Console.WriteLine({0} threw an exception of {1}, job.GetType().Name, exception.InnerException.Message);        }        private class SimpleAwaitableJob : IJob<int>        {            public SimpleAwaitableJob()            {                Priority = 1;                Repeat = false;                Enabled = true;                TaskCompletionSource = new TaskCompletionSource<int>();                Interval = TimeSpan.FromSeconds(5);                StartTime = DateTime.Now;            }            public TimeSpan Interval { get; private set; }            public DateTimeOffset StartTime { get; set; }            public int Priority { get; private set; }            public bool Repeat { get; private set; }            public bool Enabled { get; set; }            public void Return(int result)            {                TaskCompletionSource.SetResult(result);            }            public TaskCompletionSource<int> TaskCompletionSource { get; set; }        }        private class SimpleJob : IJob        {            public SimpleJob()            {                Priority = 0;                Repeat = true;       Enabled = true;            Interval = TimeSpan.FromSeconds(5);            StartTime = DateTime.Now.AddSeconds(10);        }        public TimeSpan Interval { get; private set; }        public DateTimeOffset StartTime { get; set; }        public int Priority { get; private set; }        public bool Repeat { get; private set; }        public bool Enabled { get; set; }        //We can extend it!        public int ExecutionCounter { get; set; }    }    private class SimpleUndefinedJob : IJob    {        public SimpleUndefinedJob()        {            Priority = 2;            Repeat = false;            Enabled = true;            Interval = TimeSpan.FromSeconds(5);            StartTime = DateTime.Now;        }        public TimeSpan Interval { get; private set; }        public DateTimeOffset StartTime { get; set; }        public int Priority { get; private set; }        public bool Repeat { get; private set; }        public bool Enabled { get; set; }    }}}
Flow Task Scheduler
c#;multithreading;scheduled tasks