This commit is contained in:
2023-05-31 10:19:05 +08:00
parent 1b65a7a9e5
commit 9c621c75cd
238 changed files with 9905 additions and 4034 deletions

View File

@@ -0,0 +1,81 @@
using JNPF.TaskScheduler.Entitys.Enum;
using SqlSugar;
namespace JNPF.TaskScheduler.Entitys;
[SugarTable("JobDetails", "作业信息表")]
[Tenant("JNPF-Job")]
public class JobDetails
{
/// <summary>
/// Id.
/// </summary>
[SugarColumn(ColumnDescription = "Id", IsPrimaryKey = true, IsIdentity = true)]
public virtual long Id { get; set; }
/// <summary>
/// 作业 Id.
/// </summary>
[SugarColumn(ColumnDescription = "作业Id")]
public virtual string JobId { get; set; }
/// <summary>
/// 组名称.
/// </summary>
[SugarColumn(ColumnDescription = "组名称")]
public string? GroupName { get; set; }
/// <summary>
/// 作业类型 FullName.
/// </summary>
[SugarColumn(ColumnDescription = "作业类型")]
public string? JobType { get; set; }
/// <summary>
/// 程序集 Name.
/// </summary>
[SugarColumn(ColumnDescription = "程序集")]
public string? AssemblyName { get; set; }
/// <summary>
/// 描述信息.
/// </summary>
[SugarColumn(ColumnDescription = "描述信息")]
public string? Description { get; set; }
/// <summary>
/// 是否并行执行.
/// </summary>
[SugarColumn(ColumnDescription = "是否并行执行")]
public bool Concurrent { get; set; } = true;
/// <summary>
/// 是否扫描特性触发器.
/// </summary>
[SugarColumn(ColumnDescription = "是否扫描特性触发器")]
public bool IncludeAnnotations { get; set; } = false;
/// <summary>
/// 额外数据.
/// </summary>
[SugarColumn(ColumnDescription = "额外数据", ColumnDataType = "longtext,text,clob")]
public string? Properties { get; set; } = "{}";
/// <summary>
/// 更新时间.
/// </summary>
[SugarColumn(ColumnDescription = "更新时间")]
public DateTime? UpdatedTime { get; set; }
/// <summary>
/// 作业创建类型.
/// </summary>
[SugarColumn(ColumnDescription = "作业创建类型")]
public RequestTypeEnum CreateType { get; set; } = RequestTypeEnum.BuiltIn;
/// <summary>
/// 脚本代码.
/// </summary>
[SugarColumn(ColumnDescription = "脚本代码", ColumnDataType = StaticConfig.CodeFirst_BigString)]
public string? ScriptCode { get; set; }
}

View File

@@ -0,0 +1,142 @@
using JNPF.Schedule;
using SqlSugar;
namespace JNPF.TaskScheduler.Entitys;
[SugarTable("JobTriggers", "作业触发器表")]
[Tenant("JNPF-Job")]
public class JobTriggers
{
/// <summary>
/// Id.
/// </summary>
[SugarColumn(ColumnDescription = "Id", IsPrimaryKey = true, IsIdentity = true)]
public virtual long Id { get; set; }
/// <summary>
/// 触发器 Id.
/// </summary>
[SugarColumn(ColumnDescription = "触发器Id")]
public virtual string TriggerId { get; set; }
/// <summary>
/// 作业 Id.
/// </summary>
[SugarColumn(ColumnDescription = "作业Id")]
public virtual string JobId { get; set; }
/// <summary>
/// 触发器类型 FullName.
/// </summary>
[SugarColumn(ColumnDescription = "触发器类型")]
public string? TriggerType { get; set; }
/// <summary>
/// 程序集 Name.
/// </summary>
[SugarColumn(ColumnDescription = "程序集")]
public string? AssemblyName { get; set; }
/// <summary>
/// 参数.
/// </summary>
[SugarColumn(ColumnDescription = "参数")]
public string? Args { get; set; }
/// <summary>
/// 描述信息.
/// </summary>
[SugarColumn(ColumnDescription = "描述信息")]
public string? Description { get; set; }
/// <summary>
/// 状态.
/// </summary>
[SugarColumn(ColumnDescription = "状态")]
public TriggerStatus Status { get; set; } = TriggerStatus.Ready;
/// <summary>
/// 起始时间.
/// </summary>
[SugarColumn(ColumnDescription = "起始时间")]
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间.
/// </summary>
[SugarColumn(ColumnDescription = "结束时间")]
public DateTime? EndTime { get; set; }
/// <summary>
/// 最近运行时间.
/// </summary>
[SugarColumn(ColumnDescription = "最近运行时间")]
public DateTime? LastRunTime { get; set; }
/// <summary>
/// 下一次运行时间.
/// </summary>
[SugarColumn(ColumnDescription = "下一次运行时间")]
public DateTime? NextRunTime { get; set; }
/// <summary>
/// 触发次数.
/// </summary>
[SugarColumn(ColumnDescription = "触发次数")]
public long NumberOfRuns { get; set; }
/// <summary>
/// 最大触发次数0:不限制n:N次.
/// </summary>
[SugarColumn(ColumnDescription = "最大触发次数")]
public long MaxNumberOfRuns { get; set; }
/// <summary>
/// 出错次数.
/// </summary>
[SugarColumn(ColumnDescription = "出错次数")]
public long NumberOfErrors { get; set; }
/// <summary>
/// 最大出错次数0:不限制n:N次.
/// </summary>
[SugarColumn(ColumnDescription = "最大出错次数")]
public long MaxNumberOfErrors { get; set; }
/// <summary>
/// 重试次数.
/// </summary>
[SugarColumn(ColumnDescription = "重试次数")]
public int NumRetries { get; set; }
/// <summary>
/// 重试间隔时间ms.
/// </summary>
[SugarColumn(ColumnDescription = "重试间隔时间(ms)")]
public int RetryTimeout { get; set; } = 1000;
/// <summary>
/// 是否立即启动.
/// </summary>
[SugarColumn(ColumnDescription = "是否立即启动")]
public bool StartNow { get; set; } = true;
/// <summary>
/// 是否启动时执行一次.
/// </summary>
[SugarColumn(ColumnDescription = "是否启动时执行一次")]
public bool RunOnStart { get; set; } = false;
/// <summary>
/// 是否在启动时重置最大触发次数等于一次的作业.
/// </summary>
/// <remarks>解决因持久化数据已完成一次触发但启动时不再执行的问题</remarks>
[SugarColumn(ColumnDescription = "是否在启动时重置最大触发次数等于一次的作业")]
public bool ResetOnlyOnce { get; set; } = true;
/// <summary>
/// 更新时间.
/// </summary>
[SugarColumn(ColumnDescription = "更新时间")]
public DateTime? UpdatedTime { get; set; }
}

View File

@@ -2,7 +2,7 @@
using JNPF.Common.Contracts;
using SqlSugar;
namespace JNPF.TaskScheduler.Entitys.Entity;
namespace JNPF.TaskScheduler.Entitys;
/// <summary>
/// 定时任务
@@ -11,7 +11,6 @@ namespace JNPF.TaskScheduler.Entitys.Entity;
/// 日 期2021-06-01 .
/// </summary>
[SugarTable("BASE_TIMETASK")]
[Tenant(ClaimConst.TENANTID)]
public class TimeTaskEntity : CLDEntityBase
{
/// <summary>

View File

@@ -2,7 +2,7 @@
using JNPF.Common.Contracts;
using SqlSugar;
namespace JNPF.TaskScheduler.Entitys.Entity;
namespace JNPF.TaskScheduler.Entitys;
/// <summary>
/// 定时任务日志

View File

@@ -1,23 +1,27 @@
namespace JNPF.TaskScheduler.Entitys.Enum
using System.ComponentModel;
namespace JNPF.TaskScheduler.Entitys.Enum;
/// <summary>
/// http请求类型.
/// </summary>
public enum RequestTypeEnum
{
/// <summary>
/// http请求类型.
/// 内置.
/// </summary>
public enum RequestTypeEnum
{
/// <summary>
/// Api数据.
/// </summary>
Api = 1,
[Description("内置")]
BuiltIn = 0,
/// <summary>
/// SQL操作.
/// </summary>
Sql = 2,
/// <summary>
/// 脚本.
/// </summary>
[Description("脚本")]
Script = 1,
/// <summary>
/// 执行本地任务.
/// </summary>
Run = 3,
}
/// <summary>
/// HTTP请求.
/// </summary>
[Description("HTTP请求")]
Http = 2,
}

View File

@@ -1,7 +1,7 @@
using JNPF.Common.Extension;
using JNPF.Common.Security;
using JNPF.TaskScheduler.Entitys;
using JNPF.TaskScheduler.Entitys.Dto.TaskScheduler;
using JNPF.TaskScheduler.Entitys.Entity;
using JNPF.TaskScheduler.Entitys.Model;
using Mapster;

View File

@@ -1,8 +1,5 @@
using JNPF.Common.Security;
using JNPF.DependencyInjection;
using JNPF.Logging;
using JNPF.DependencyInjection;
using JNPF.Systems.Entitys.Permission;
using JNPF.TaskScheduler.Entitys.Entity;
using SqlSugar;
namespace JNPF.TaskScheduler.Listener;
@@ -12,55 +9,42 @@ namespace JNPF.TaskScheduler.Listener;
/// </summary>
public class SpareTimeDemo : ISpareTimeWorker
{
/// <summary>
/// 3秒后出勤统计.
/// </summary>
/// <param name="timer">参数</param>
/// <param name="count">次数</param>
[SpareTime("* * * * * ?", "生成雪花Id", ExecuteType = SpareTimeExecuteTypes.Serial)]
public void GenerateSnowId(SpareTimer timer, long count)
{
// 创建作用域
Scoped.Create((factory, scope) =>
/// <summary>
/// 3秒后出勤统计.
/// </summary>
/// <param name="timer">参数</param>
/// <param name="count">次数</param>
[SpareTime("* * * * * ?", "执行Sql", ExecuteType = SpareTimeExecuteTypes.Serial)]
public void ExecSql(SpareTimer timer, long count)
{
try
{
// 数据库操作
var sqlSugarRepository = App.GetService<ISqlSugarRepository<SnowIdEntity>>(scope.ServiceProvider);
List<SnowIdEntity> ls = new List<SnowIdEntity>();
for (int i = 0; i < 50; i++)
// 创建作用域
Scoped.Create((factory, scope) =>
{
ls.Add(new SnowIdEntity { Id = SnowflakeIdHelper.NextId() });
Thread.Sleep(1);
}
sqlSugarRepository.InsertRange(ls);
}
catch (Exception ex)
{
Log.Error("GenerateSnowId错误", ex);
}
});
}
// 数据库操作
var sqlSugarRepository = App.GetService<ISqlSugarRepository<UserEntity>>(scope.ServiceProvider);
sqlSugarRepository.DeleteById("226890444955452677");
});
}
/// <summary>
/// 3秒后出勤统计.
/// </summary>
/// <param name="timer">参数</param>
/// <param name="count">次数</param>
[SpareTime("0 0/1 * * * ?", "执行Sql1", ExecuteType = SpareTimeExecuteTypes.Serial)]
public void ExecSql1(SpareTimer timer, long count)
{
// 创建作用域
Scoped.Create((factory, scope) =>
/// <summary>
/// 3秒后出勤统计.
/// </summary>
/// <param name="timer">参数</param>
/// <param name="count">次数</param>
[SpareTime("0 0/1 * * * ?", "执行Sql1", ExecuteType = SpareTimeExecuteTypes.Serial)]
public void ExecSql1(SpareTimer timer, long count)
{
var start = DateTime.Now;
Console.WriteLine(start.ToString("yyyy-MM-dd HH:mm:ss") + ":任务开始-----------");
// 数据库操作
var sqlSugarRepository = App.GetService<ISqlSugarRepository<UserEntity>>(scope.ServiceProvider);
sqlSugarRepository.DeleteById("226890444955452677");
var end = DateTime.Now;
Console.WriteLine(end.ToString("yyyy-MM-dd HH:mm:ss") + ":任务结束-----------");
Console.WriteLine($"SQL执行了{count} 次,耗时:{(end - start).TotalMilliseconds}ms");
});
}
// 创建作用域
Scoped.Create((factory, scope) =>
{
var start = DateTime.Now;
Console.WriteLine(start.ToString("yyyy-MM-dd HH:mm:ss") + ":任务开始-----------");
// 数据库操作
var sqlSugarRepository = App.GetService<ISqlSugarRepository<UserEntity>>(scope.ServiceProvider);
sqlSugarRepository.DeleteById("226890444955452677");
var end = DateTime.Now;
Console.WriteLine(end.ToString("yyyy-MM-dd HH:mm:ss") + ":任务结束-----------");
Console.WriteLine($"SQL执行了{count} 次,耗时:{(end - start).TotalMilliseconds}ms");
});
}
}

View File

@@ -4,8 +4,7 @@ using JNPF.Common.Security;
using JNPF.DependencyInjection;
using JNPF.EventBus;
using JNPF.EventHandler;
using JNPF.Systems.Entitys.System;
using Microsoft.Extensions.DependencyInjection;
using JNPF.TaskScheduler.Entitys;
using SqlSugar;
namespace JNPF.TaskScheduler.Listener;

View File

@@ -12,12 +12,13 @@ using JNPF.DependencyInjection;
using JNPF.DynamicApiController;
using JNPF.FriendlyException;
using JNPF.LinqBuilder;
using JNPF.Schedule;
using JNPF.Systems.Interfaces.System;
using JNPF.TaskScheduler.Entitys;
using JNPF.TaskScheduler.Entitys.Dto.TaskScheduler;
using JNPF.TaskScheduler.Entitys.Entity;
using JNPF.TaskScheduler.Entitys.Enum;
using JNPF.TaskScheduler.Entitys.Model;
using JNPF.TaskScheduler.Interfaces.TaskScheduler;
using JNPF.TimeCrontab;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
@@ -38,6 +39,8 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
private readonly IDataInterfaceService _dataInterfaceService;
private readonly IUserManager _userManager;
private readonly ICacheManager _cacheManager;
//private readonly ISchedulerFactory _schedulerFactory;
private readonly IDataBaseManager _dataBaseManager;
/// <summary>
/// 初始化一个<see cref="TimeTaskService"/>类型的新实例.
@@ -46,12 +49,16 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
ISqlSugarRepository<TimeTaskEntity> repository,
IUserManager userManager,
IDataInterfaceService dataInterfaceService,
ICacheManager cacheManager)
ICacheManager cacheManager,
//ISchedulerFactory schedulerFactory,
IDataBaseManager dataBaseManager)
{
_repository = repository;
_userManager = userManager;
_dataInterfaceService = dataInterfaceService;
_cacheManager = cacheManager;
_dataBaseManager = dataBaseManager;
//_schedulerFactory = schedulerFactory;
}
#region Get
@@ -124,6 +131,7 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
{
return await GetTaskMethods();
}
#endregion
#region Post
@@ -131,7 +139,7 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
/// <summary>
/// 新建.
/// </summary>
/// <param name="input">实体对象</param>
/// <param name="input">实体对象.</param>
/// <returns></returns>
[HttpPost("")]
public async Task Create([FromBody] TimeTaskCrInput input)
@@ -147,10 +155,14 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
entity.ExecuteContent = comtentModel.ToJsonString();
entity.ExecuteCycleJson = comtentModel.cron;
var result = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync();
// var job = _repository.AsTenant().GetConnection("JNPF-Job");
// var jobDetail = new JobDetail() { };
// job.Insertable()
_ = result ?? throw Oops.Oh(ErrorCode.COM1000);
// 添加到任务调度里
AddTimerJob(result);
//await AddJob(result);
}
/// <summary>
@@ -271,7 +283,7 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
// 非多租户模式启动自启任务
if (!KeyVariable.MultiTenancy)
{
_repository.AsQueryable().Where(x => x.DeleteMark == null && x.EnabledMark == 1).ToList().ForEach(AddTimerJob);
//_repository.AsQueryable().Where(x => x.DeleteMark == null && x.EnabledMark == 1).ToList().ForEach(AddTimerJob);
}
}
@@ -324,12 +336,11 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
Action<SpareTimer, long>? action = null;
ContentModel? comtentModel = input.ExecuteContent.ToObject<ContentModel>();
input.ExecuteCycleJson = comtentModel.cron;
TaskMethodInfo? taskMethod = null;
switch (input.ExecuteType)
{
case "3":
// 查询符合条件的任务方法
taskMethod = GetTaskMethods()?.Result.FirstOrDefault(m => m.id == comtentModel.localHostTaskId);
TaskMethodInfo? taskMethod = GetTaskMethods()?.Result.FirstOrDefault(m => m.id == comtentModel.localHostTaskId);
if (taskMethod == null) break;
// 创建任务对象
@@ -347,7 +358,8 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
}
if (action == null) return;
//SpareTime.Do(comtentModel.cron, action, input.Id, comtentModel.ConnectionConfig.ToJsonString(), true, executeType: SpareTimeExecuteTypes.Parallel);
// SpareTime.Do(comtentModel.cron, action, input.Id, comtentModel.ConnectionConfig.ToJsonString(), true, executeType: SpareTimeExecuteTypes.Parallel);
var starTime = comtentModel.startTime?.TimeStampToDateTime();
var endTime = comtentModel.endTime?.TimeStampToDateTime();
var interval = 1;
@@ -355,65 +367,86 @@ public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransie
{
interval = (starTime.ParseToDateTime() - DateTime.Now).TotalMilliseconds.ParseToInt();
}
if (taskMethod.StartNow) //modifyby zhoukeda 20230516
{
SpareTime.DoOnce(interval, action, "Once_" + input.Id);
}
Func<DateTimeOffset?> nextHandle = null;
var isRun = comtentModel.endTime.IsNullOrEmpty() ? DateTime.Now >= starTime : DateTime.Now >= starTime && DateTime.Now < endTime;
if (isRun)
{
nextHandle = ()=>SpareTime.GetCronNextOccurrence(comtentModel.cron);
}
SpareTime.Do(nextHandle
,
SpareTime.DoOnce(interval, action, "Once_" + input.Id);
SpareTime.Do(
() =>
{
var isRun = comtentModel.endTime.IsNullOrEmpty() ? DateTime.Now >= starTime : DateTime.Now >= starTime && DateTime.Now < endTime;
if (isRun)
{
return SpareTime.GetCronNextOccurrence(comtentModel.cron);
}
else
{
return null;
}
},
action, input.Id, comtentModel.ConnectionConfig.ToJsonString(), true, executeType: SpareTimeExecuteTypes.Parallel, cancelInNoneNextTime: false);
}
private async Task AddJob(TimeTaskEntity input)
{
//ContentModel? comtentModel = input.ExecuteContent.ToObject<ContentModel>();
//var starTime = comtentModel.startTime?.TimeStampToDateTime();
//var endTime = comtentModel.endTime?.TimeStampToDateTime();
//var jobBuilder = JobBuilder.Create(async (context, stoppingToken) =>
//{
// Console.WriteLine(string.Format("{0}在执行任务,执行时间{1},触发时间:{1}", context.JobId, context.ExecutingTime, context.OccurrenceTime));
// if (!input.ExecuteType.Equals("3"))
// {
// var msg = await PerformJob(input);
// }
//});
//jobBuilder.SetJobId(input.Id);
//jobBuilder.SetGroupName(input.FullName);
//var triggerBuilder = TriggerBuilder.Create<CronTrigger>(input.ExecuteCycleJson, CronStringFormat.WithSeconds);
//triggerBuilder.SetStartTime(starTime);
//triggerBuilder.SetEndTime(endTime);
////triggerBuilder.SetRunOnStart(true);
//_schedulerFactory.AddJob(jobBuilder, triggerBuilder);
}
/// <summary>
/// 获取所有本地任务.
/// </summary>
/// <returns></returns>
private async Task<List<TaskMethodInfo>> GetTaskMethods()
{
// var taskMethods = await _cacheManager.GetAsync<List<TaskMethodInfo>>(CommonConst.CACHEKEYTIMERJOB);
// if (taskMethods != null) return taskMethods;
//var taskMethods = await _cacheManager.GetAsync<List<TaskMethodInfo>>(CommonConst.CACHEKEYTIMERJOB);
//if (taskMethods != null) return taskMethods;
List<TaskMethodInfo> taskMethods = null;
// 获取所有本地任务方法必须有spareTimeAttribute特性
taskMethods = App.EffectiveTypes
.Where(u => u.IsClass && !u.IsInterface && !u.IsAbstract && typeof(ISpareTimeWorker).IsAssignableFrom(u))
.SelectMany(u => u.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(m => m.GetCustomAttributes(typeof(SpareTimeAttribute), false).ToString().Contains("SpareTime") &&
m.GetParameters().Length == 2 &&
m.GetParameters()[0].ParameterType == typeof(SpareTimer) &&
m.GetParameters()[1].ParameterType == typeof(long) && m.ReturnType == typeof(void))
.Select(m =>
{
// 默认获取第一条任务特性
var spareTimeAttribute = m.GetCustomAttribute<SpareTimeAttribute>();
return new TaskMethodInfo
{
id = $"{m.DeclaringType.Name}/{m.Name}",
fullName = spareTimeAttribute.WorkerName,
RequestUrl = $"{m.DeclaringType.Name}/{m.Name}",
cron = spareTimeAttribute.CronExpression,
DoOnce = spareTimeAttribute.DoOnce,
ExecuteType = spareTimeAttribute.ExecuteType,
Interval = (int)spareTimeAttribute.Interval / 1000,
StartNow = spareTimeAttribute.StartNow,
RequestType = RequestTypeEnum.Run,
Remark = spareTimeAttribute.Description,
TimerType = string.IsNullOrEmpty(spareTimeAttribute.CronExpression) ? SpareTimeTypes.Interval : SpareTimeTypes.Cron,
MethodName = m.Name,
DeclaringType = m.DeclaringType
};
})).ToList();
await _cacheManager.SetAsync(CommonConst.CACHEKEYTIMERJOB, taskMethods);
return taskMethods;
//// 获取所有本地任务方法必须有spareTimeAttribute特性
//taskMethods = App.EffectiveTypes
// .Where(u => u.IsClass && !u.IsInterface && !u.IsAbstract && typeof(ISpareTimeWorker).IsAssignableFrom(u))
// .SelectMany(u => u.GetMethods(BindingFlags.Public | BindingFlags.Instance)
// .Where(m => m.IsDefined(typeof(SpareTimeAttribute), false) &&
// m.GetParameters().Length == 2 &&
// m.GetParameters()[0].ParameterType == typeof(SpareTimer) &&
// m.GetParameters()[1].ParameterType == typeof(long) && m.ReturnType == typeof(void))
// .Select(m =>
// {
// // 默认获取第一条任务特性
// var spareTimeAttribute = m.GetCustomAttribute<SpareTimeAttribute>();
// return new TaskMethodInfo
// {
// id = $"{m.DeclaringType.Name}/{m.Name}",
// fullName = spareTimeAttribute.WorkerName,
// RequestUrl = $"{m.DeclaringType.Name}/{m.Name}",
// cron = spareTimeAttribute.CronExpression,
// DoOnce = spareTimeAttribute.DoOnce,
// ExecuteType = spareTimeAttribute.ExecuteType,
// Interval = (int)spareTimeAttribute.Interval / 1000,
// StartNow = spareTimeAttribute.StartNow,
// RequestType = RequestTypeEnum.BuiltIn,
// Remark = spareTimeAttribute.Description,
// TimerType = string.IsNullOrEmpty(spareTimeAttribute.CronExpression) ? SpareTimeTypes.Interval : SpareTimeTypes.Cron,
// MethodName = m.Name,
// DeclaringType = m.DeclaringType
// };
// })).ToList();
//await _cacheManager.SetAsync(CommonConst.CACHEKEYTIMERJOB, taskMethods);
//return taskMethods;
return new List<TaskMethodInfo>();
}
#endregion

View File

@@ -16,8 +16,4 @@
<ProjectReference Include="..\Tnb.TaskScheduler.Interfaces\Tnb.TaskScheduler.Interfaces.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Tnb.Core" Version="2023.3.24.1010" />
</ItemGroup>
</Project>