public async void RunJobOnce() { var cts = new CancellationTokenSource(); var clock = new Clock(new DateTime(1970, 1, 1)); var delay = new Delay(); var scheduler = JobScheduler <string> .Start(cts.Token, clock.GetCurrentTime, delay.Start); var jobStarted = WaitEventAsync <JobStartedEventArgs <string> >(h => scheduler.JobStarted += h, h => scheduler.JobStarted -= h); var jobEnded = WaitEventAsync <JobEndedEventArgs <string> >(h => scheduler.JobEnded += h, h => scheduler.JobEnded -= h); var jobRemoved = WaitEventAsync <JobRemovalEventArgs <string> >(h => scheduler.JobRemoved += h, h => scheduler.JobRemoved -= h); const string id = "foo"; var ran = false; var thisThread = Thread.CurrentThread; Thread jobThread = null; scheduler.AddJob(id, clock.Time.AddSeconds(1), _ => { ran = true; jobThread = Thread.CurrentThread; return(Task.FromResult(0)); }); clock.Time += TimeSpan.FromSeconds(1); delay.Done(); await await Task.WhenAny(jobStarted, scheduler.Task); Assert.False(scheduler.Task.IsCompleted); Assert.Equal(TimeSpan.FromSeconds(1), delay.Duration); var jobStartedEventArgs = await jobStarted; Assert.NotNull(jobStartedEventArgs); Assert.Equal(id, jobStartedEventArgs.Job); Assert.Equal(clock.Time, jobStartedEventArgs.StartTime); await jobStartedEventArgs.Task; Assert.True(ran); Assert.NotEqual(thisThread, jobThread); await await Task.WhenAny(jobEnded, scheduler.Task); Assert.False(scheduler.Task.IsCompleted); var jobEndedEventArgs = await jobEnded; Assert.NotNull(jobEndedEventArgs); Assert.Equal(jobStartedEventArgs.Job, jobEndedEventArgs.Job); Assert.Equal(jobStartedEventArgs.Task, jobEndedEventArgs.Task); Assert.Equal(clock.Time, jobEndedEventArgs.EndTime); await await Task.WhenAny(jobRemoved, scheduler.Task); Assert.False(scheduler.Task.IsCompleted); var jobRemovedEventArgs = await jobRemoved; Assert.NotNull(jobRemovedEventArgs); Assert.Equal(jobStartedEventArgs.Job, jobRemovedEventArgs.Job); Assert.Equal(JobRemovalReason.EndOfSchedule, jobRemovedEventArgs.Reason); cts.Cancel(); await scheduler.Task; }