/// <summary> /// /// </summary> /// <param name="services"></param> public ServerBootstrap(IServiceProvider services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } var options = new ServerOptions(); var types = GetTypeInfos(options as ServerOptions); var list = new List <JobExecutor>(); foreach (var type in types) { foreach (var method in type.DeclaredMethods) { var attribute = method.GetCustomAttribute <ScheduleAttribute>(); if (attribute != null) { if (string.IsNullOrEmpty(attribute.Name)) { throw new CustomAttributeFormatException("Crontab name is empty"); } var arr = attribute.Schedule.Split('|'); if (arr.Length == 0) { throw new CustomAttributeFormatException($"Crontab '{attribute.Name}' does not have any schedule"); } var schedules = new JobSchedule[arr.Length]; for (int i = 0; i < arr.Length; i++) { if (JobSchedule.TryParse(arr[i], out JobSchedule schedule)) { schedules[i] = schedule; } else { throw new CustomAttributeFormatException($"Crontab '{attribute.Name}' schedule '{arr[i]}' format error"); } } var name = attribute.Name; if (string.IsNullOrEmpty(name)) { name = method.Name; } var item = new JobExecutor(name, services, cts.Token, type, method, schedules, attribute.AllowConcurrentExecution, attribute.RunImmediately); if (!executorDict.ContainsKey(item.Name)) { executorDict.Add(item.Name, item); if (attribute.AutoEnable) { item.Enable(); } } else { throw new CustomAttributeFormatException($"Crontab '{item.Name}' name is duplicate"); } } } } var dt = DateTime.Now; dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0); var next = dt.AddMinutes(1); var due = Convert.ToInt32(Math.Ceiling((next - DateTime.Now).TotalMilliseconds)); Task.Factory.StartNew(async() => { try { await Task.Delay(due, cts.Token); Execute(); } catch (Exception ex) { LogAgent.Error(ex.ToString()); } }, cts.Token); }