1

好吧,我创建了一个具有许多功能的作业调度程序;但是我真的很想使用 .Net 4.5 Async/Await 功能来等待作业完成执行。

-代码

调度程序.cs

public abstract class Scheduler
{
    #region Fields && Properties

    private readonly List<Job> _jobs = new List<Job>();
    private readonly Random _rand = new Random();
    private Job _currentlyExecutingJob;
    private Thread _workingThread;
    public bool? Parallel { get; private set; }
    public DateTimeOffset NextExecutionTime { get; private set; }
    public string ID { get; set; }
    public abstract Task JobTrigger(Job job);
    public abstract void UnobservedException(Exception exception, Job job);

    #endregion

    #region Ctor

    protected Scheduler(bool parallel) { Parallel = parallel; }

    #endregion

    #region Fluent

    public Scheduler Start()
    {
        if (Equals(_workingThread, null)) {
            _workingThread = new Thread(ReviewJobs);
            _workingThread.Start();
        }
        return this;
    }

    public Scheduler Stop()
    {
        if (!Equals(_workingThread, null)) {
            _workingThread.Abort();
            _workingThread = null;
        }
        return this;
    }

    #endregion

    #region Events

    private void ReviewJobs()
    {
        while (!Equals(_workingThread, null)) {
            IEnumerable<Job> jobsToExecute = from job in _jobs
                                             where job.NextExecutionTime <= DateTimeOffset.Now
                                             orderby job.Priority
                                             select job;

            if (!jobsToExecute.Any()) {
                Thread.Sleep(100);
                continue;
            }

            try {
                foreach (Job job in jobsToExecute) {
                    Job o = _currentlyExecutingJob = job;

                    if (Parallel != null && (bool)Parallel) {
                        JobTrigger(o);
                    } else {
                        JobTrigger(o).Wait();
                    }

                    if (!o.Repeat)
                        _jobs.Remove(o);
                    else if (o.Interval != null)
                        o.NextExecutionTime = DateTimeOffset.Now.Add((TimeSpan)(o.RandomizeExecution
                                                                                        ? TimeSpan.FromSeconds(_rand.Next((int)((TimeSpan)o.Interval).TotalSeconds, ((int)((TimeSpan)o.Interval).TotalSeconds + 30)))
                                                                                        : o.Interval));
                }
            } catch (Exception exception) {
                UnobservedException(exception, _currentlyExecutingJob);
            } finally {
                NextExecutionTime = (from job in _jobs
                                     where job.NextExecutionTime <= DateTimeOffset.Now
                                     orderby job.Priority
                                     select job.NextExecutionTime).FirstOrDefault();
            }
        }
    }

    #endregion

    #region Helper Methods

    public Job GetJob(string id) { return _jobs.Find(job => job.ID == id); }

    public Job GetJob(Job job) { return _jobs.Find(x => x == job); }

    public IEnumerable<Job> GetAllJobs() { return _jobs; }

    public void AddJob(Job job, bool overwrite = false)
    {
        Job existingJob = GetJob(job);

        if (null != existingJob) {
            if (overwrite) {
                _jobs.RemoveAll(jobs => jobs == existingJob);
                _jobs.Add(job);
            } else {
                _jobs.Add(job);
            }
        } else {
            _jobs.Add(job);
        }
    }

    public bool RemoveJob(string id)
    {
        Job existingJob = GetJob(id);

        if (null != existingJob) {
            return _jobs.Remove(existingJob);
        }

        return false;
    }

    public bool RemoveJob(Job job)
    {
        Job existingJob = GetJob(job);

        if (null != existingJob) {
            return _jobs.Remove(existingJob);
        }

        return false;
    }

    public void RemoveAllJobs() { _jobs.RemoveRange(0, _jobs.Count); }

    #endregion
}

作业.cs

public class Job
{
    public string ID { get; set; }
    public TimeSpan Interval { get; private set; }
    public DateTimeOffset NextExecutionTime { get; set; }
    public int Priority { get; set; }
    public bool Repeat { get; private set; }
    public bool RandomizeExecution { get; set; }
    public object Data { get; set; }

    #region Fluent

    public Job RunOnceAt(DateTimeOffset executionTime)
    {
        NextExecutionTime = executionTime;
        Repeat = false;
        return this;
    }

    public Job RepeatFrom(DateTimeOffset executionTime, TimeSpan interval)
    {
        NextExecutionTime = executionTime;
        Interval = interval;
        Repeat = true;
        return this;
    }

    #endregion
}

-用法

public class SchedulerUsage : Scheduler
{
    public SchedulerUsage(bool parallel) : base(parallel) {
    }

    public override async Task JobTrigger(Job job) 
    {
        switch (job.ID) {
                //Handle Jobs
        }
    }

    public override void UnobservedException(Exception exception, Job job) 
    { 
        //Handle Exceptions
    }

    /// <summary>
    /// Example of adding job
    /// </summary>
    public void ExampleUsage()
    {
        Job job = new Job
                  {
                          ID = "ID",
                          Data = "ATTACH SOME DATA"
                  }.RunOnceAt(DateTimeOffset.Now.AddSeconds(7));

        //Add the job... [HERE IS WHAT I WANT TO ACHIVE]
        /*await*/base.AddJob(job);

        //Start the scheduler...
        base.Start();
    }
}

问题:在我上面的实现中,如何使用 async/await 来等待作业的执行。

注意:如果我的问题看起来有点复杂,我很抱歉,但这对我来说非常必要,所以请耐心等待。

4

0 回答 0