using Castle.MicroKernel.Lifestyle;
using Castle.MicroKernel.Registration;
using CommonServiceLocator;
using System.Collections.Concurrent;
using System.Threading.Tasks;
namespace CTePack.Service;
public class MeuJob : IBackgroundJob
private readonly ISession session;
public MeuJob(ISession session)
Console.WriteLine("MeuJob " + DateTime.Now);
public class MeuJob2 : IBackgroundJob
private readonly ISession session;
public MeuJob2(ISession session)
Console.WriteLine("MeuJob2 " + DateTime.Now);
public interface IBackgroundJobExecutor
Type JobType { get; set; }
int TempoSegundos { get; set; }
event EventHandler OnStop;
event EventHandler OnStart;
public class BackgroundJobExecutor : IBackgroundJobExecutor
public Type JobType { get; set; }
public int TempoSegundos { get; set; }
public event EventHandler OnStop;
public event EventHandler OnStart;
private bool _emExecucao;
private readonly object @locker = new();
private readonly ILog _logger = LogManager.GetLogger(nameof(BackgroundJobExecutor));
public BackgroundJobExecutor(Type jobType, int tempoSegundos)
TempoSegundos = tempoSegundos;
Interval = TimeSpan.FromSeconds(TempoSegundos).TotalMilliseconds,
timer.Elapsed += new ElapsedEventHandler(ExecutarTask);
OnStart.Invoke(this, EventArgs.Empty);
OnStop.Invoke(this, EventArgs.Empty);
private void ExecutarTask(object sender, ElapsedEventArgs e)
Task.Factory.StartNew(ExecutarServico);
private void ExecutarServico()
_logger.InfoFormat("{0} - Iniciando execucao Job: {1}", DateTime.Now.ToString("G"), JobType);
using (var scope = ServiceLocator.Current.GetInstance<IWindsorContainer>().BeginScope())
var job = ServiceLocator.Current.GetInstance(JobType) as IBackgroundJob;
_logger.InfoFormat("{0} - Finalizando execucao Job: {1}", DateTime.Now.ToString("G"), JobType);
_logger.ErrorFormat("Erro na execução do serviço. Mensagem de erro: {0}", arg);
public interface IBackgroundJob
public class BackgroundJobMetadata
public Type JobType { get; set; }
public int IntervalInSeconds { get; set; }
public bool IsRunning { get; set; } = false;
public bool IsStopped { get; set; } = true;
public BackgroundJobExecutor Executor { get; set; }
public static class BackgroundJobManager
private readonly static ConcurrentDictionary<Type, BackgroundJobMetadata> JobsToRun = new();
public static void AddBackgroundJob<T>(int intervalInSeconds) where T : IBackgroundJob
AddBackgroundJob(typeof(T), intervalInSeconds);
public static void AddBackgroundJob(Type jobType, int intervalInSeconds)
var jobData = new BackgroundJobMetadata
IntervalInSeconds = intervalInSeconds,
Executor = new BackgroundJobExecutor(jobType, intervalInSeconds),
jobData.Executor.OnStop += Executor_OnStop;
jobData.Executor.OnStart += Executor_OnStart;
JobsToRun.TryAdd(jobType, jobData);
public static void AddOrUpdateBackgroundJob<T>(int intervalInSeconds) where T : IBackgroundJob
AddOrUpdateBackgroundJob(typeof(T), intervalInSeconds);
public static void AddOrUpdateBackgroundJob(Type jobType, int intervalInSeconds)
if (JobsToRun.TryGetValue(jobType, out var jobMetadata) && jobMetadata.IsRunning)
throw new InvalidOperationException();
new BackgroundJobMetadata
IntervalInSeconds = intervalInSeconds,
Executor = new BackgroundJobExecutor(jobType, intervalInSeconds)
oldValue.IsStopped = true;
oldValue.IsRunning = false;
oldValue.IntervalInSeconds = intervalInSeconds;
oldValue.Executor = new BackgroundJobExecutor(jobType, intervalInSeconds);
public static void RemoveBackgroundJob<T>() where T : IBackgroundJob
RemoveBackgroundJob(typeof(T));
public static void RemoveBackgroundJob(Type jobType)
if (!JobsToRun.TryGetValue(jobType, out var jobMetadata))
throw new InvalidOperationException();
if (jobMetadata.IsRunning)
jobMetadata.Executor.Stop();
JobsToRun.TryRemove(jobType, out _);
public static void Start()
foreach (var (_, jobMetadata) in JobsToRun)
if (jobMetadata.IsStopped)
jobMetadata.Executor.Start();
public static void Start(Type jobType)
if (!JobsToRun.TryGetValue(jobType, out var jobMetadata))
throw new InvalidOperationException();
if (jobMetadata.IsRunning)
throw new InvalidOperationException();
jobMetadata.Executor.Start();
public static void Stop()
foreach (var (_, jobMetadata) in JobsToRun)
if (jobMetadata.IsRunning)
jobMetadata.Executor.Stop();
public static void Stop(Type jobType)
if (!JobsToRun.TryGetValue(jobType, out var jobMetadata))
throw new InvalidOperationException();
if (jobMetadata.IsRunning)
throw new InvalidOperationException();
jobMetadata.Executor.Stop();
private static void Executor_OnStart(object sender, EventArgs e)
var executor = sender as BackgroundJobExecutor;
JobStarted(executor.JobType);
private static void Executor_OnStop(object sender, EventArgs e)
var executor = sender as BackgroundJobExecutor;
JobStopped(executor.JobType);
private static void JobStarted(Type jobType)
if (!JobsToRun.TryGetValue(jobType, out var jobMetadata))
throw new InvalidOperationException();
jobMetadata.IsRunning = true;
jobMetadata.IsStopped = false;
private static void JobStopped(Type jobType)
if (!JobsToRun.TryGetValue(jobType, out var jobMetadata))
throw new InvalidOperationException();
jobMetadata.IsStopped = true;
jobMetadata.IsRunning = false;
public static class BackgroundJobExtensions
public static IWindsorContainer RegisterBackgroundJobsFromAssembly(this IWindsorContainer container, Assembly assembly)
Classes.FromAssembly(assembly)
.BasedOn(typeof(IBackgroundJob))