Hyz.FreeScheduler
0.1.0
.NET 8.0
This package targets .NET 8.0. The package is compatible with this framework or higher.
.NET Standard 2.0
This package targets .NET Standard 2.0. The package is compatible with this framework or higher.
dotnet add package Hyz.FreeScheduler --version 0.1.0
NuGet\Install-Package Hyz.FreeScheduler -Version 0.1.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Hyz.FreeScheduler" Version="0.1.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Hyz.FreeScheduler" Version="0.1.0" />
<PackageReference Include="Hyz.FreeScheduler" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Hyz.FreeScheduler --version 0.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Hyz.FreeScheduler, 0.1.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Hyz.FreeScheduler@0.1.0
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Hyz.FreeScheduler&version=0.1.0
#tool nuget:?package=Hyz.FreeScheduler&version=0.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Hyz.FreeScheduler
基于开源 FreeScheduler 封装轻量化定时任务调度,支持集群任务、临时的延时任务和重复循环任务,可按秒、每天/每周/每月固定时间、自定义间隔执行。
特性
- 支持
netstandard2.0;net8.0;net9.0;net10.0多目标框架 - 基于 FreeRedis 持久化,支持单节点、集群、哨兵、主从四种 Redis 连接模式
- 自动扫描程序集中的
BaseJob子类并注册 - 支持 5 种任务间隔方式:按秒(SEC)、每天(RunOnDay)、每周(RunOnWeek)、每月(RunOnMonth)、自定义(Custom)
- JobId/Expression 优先级规则:
ScheduledJobAttribute> 类重写 - CancellationToken 异步取消支持
- 自动清理日志任务
- Redis 缓存 TaskInterval 以枚举名称存储,可读性强
快速开始
1. 安装 NuGet 包
dotnet add package Hyz.FreeScheduler
2. 配置 appsettings.json
{
"Redis": {
"ConnectionString": "127.0.0.1:6379,password=xxx,poolsize=10,defaultDatabase=1"
},
"AutoClean": {
"Enabled": true,
"Expression": "0 0 0 1 * ?"
}
}
3. 注册服务
using Hyz.FreeScheduler.Extensions;
builder.Services.AddHyzFreeSchedulerService(
configureOptions: config =>
{
config.Redis = new RedisConfig()
{
ConnectionString = configuration.GetValue<string>("Redis:ConnectionString")!
};
config.AutoClean = new AutoCleanLogConfig()
{
Enabled = configuration.GetValue<bool>("AutoClean:Enabled"),
Expression = configuration.GetValue<string?>("AutoClean:Expression") ?? "0 0 0 1 * ?"
};
},
loggingBuilder: loggingBuilder => loggingBuilder.AddNLog(),
assembly: typeof(Program).Assembly
);
var app = builder.Build();
// 停止时释放资源
app.Services.UseHyzDisposeFreeScheduler();
Redis 连接模式
支持四种 Redis 连接模式,通过 RedisConfig.Mode 指定,默认为 Single。
Single - 单节点(默认)
{
"Redis": {
"ConnectionString": "127.0.0.1:6379,password=xxx,defaultDatabase=1"
}
}
Cluster - 集群模式
只需提供部分主节点地址,客户端自动发现全部节点。
{
"Redis": {
"Mode": "Cluster",
"Hosts": [
"192.168.0.2:7001",
"192.168.0.2:7002",
"192.168.0.2:7003"
]
}
}
Sentinel - 哨兵模式
ConnectionString 提供连接参数(如 password),MasterName 为哨兵监控的 master 名称,Hosts 为哨兵节点地址(默认端口 26379)。
{
"Redis": {
"Mode": "Sentinel",
"ConnectionString": "password=xxx,defaultDatabase=1",
"MasterName": "mymaster",
"Hosts": [
"192.168.1.10:26379",
"192.168.1.11:26379",
"192.168.1.12:26379"
],
"ReadWriteSeparate": true
}
}
| 参数 | 说明 |
|---|---|
MasterName |
哨兵配置中的 master 名称 |
Hosts |
哨兵节点地址列表 |
ReadWriteSeparate |
true=读走 slave/写走 master,false=读写都走 master |
MasterSlave - 主从模式
ConnectionString 为主节点(写),Slaves 为从节点列表(读,随机选择)。
{
"Redis": {
"Mode": "MasterSlave",
"ConnectionString": "127.0.0.1:6379,password=xxx,defaultDatabase=1",
"Slaves": [
"127.0.0.1:6380,password=xxx,defaultDatabase=1",
"127.0.0.1:6381,password=xxx,defaultDatabase=1"
]
}
}
代码配置示例
// 集群模式
config.Redis = new RedisConfig
{
Mode = RedisMode.Cluster,
Hosts = new[] { "192.168.0.2:7001", "192.168.0.2:7002", "192.168.0.2:7003" }
};
// 哨兵模式
config.Redis = new RedisConfig
{
Mode = RedisMode.Sentinel,
ConnectionString = "password=xxx,defaultDatabase=1",
MasterName = "mymaster",
Hosts = new[] { "192.168.1.10:26379", "192.168.1.11:26379" },
ReadWriteSeparate = true
};
// 主从模式
config.Redis = new RedisConfig
{
Mode = RedisMode.MasterSlave,
ConnectionString = "127.0.0.1:6379,password=xxx",
Slaves = new[] { "127.0.0.1:6380,password=xxx", "127.0.0.1:6381,password=xxx" }
};
定义定时任务
继承 BaseJob 并使用 [ScheduledJob] 特性标记:
Custom(默认)- CRON 表达式
[ScheduledJob(nameof(TestJob), Expression = "0/5 * * * * ?")]
public class TestJob : BaseJob
{
public override async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
// TODO: 实现任务逻辑
await Task.CompletedTask;
}
}
SEC - 按秒触发
[ScheduledJob(nameof(IntervalJob), TaskInterval = TaskInterval.SEC, Expression = "10")]
public class IntervalJob : BaseJob
{
public override async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
await Task.CompletedTask;
}
}
RunOnDay - 每天固定时间
[ScheduledJob(nameof(DailyJob), TaskInterval = TaskInterval.RunOnDay, Expression = "20:00:00")]
public class DailyJob : BaseJob
{
public override async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
await Task.CompletedTask;
}
}
RunOnWeek - 每周固定时间
// 每周一 20:00:00 执行(格式: 周几:时:分:秒)
[ScheduledJob(nameof(WeeklyJob), TaskInterval = TaskInterval.RunOnWeek, Expression = "1:20:00:00")]
public class WeeklyJob : BaseJob
{
public override async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
await Task.CompletedTask;
}
}
RunOnMonth - 每月固定时间
// 每月1日 20:00:00 执行(格式: 日:时:分:秒)
[ScheduledJob(nameof(MonthlyJob), TaskInterval = TaskInterval.RunOnMonth, Expression = "1:20:00:00")]
public class MonthlyJob : BaseJob
{
public override async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
await Task.CompletedTask;
}
}
JobId / Expression 优先级规则
JobId 和 Expression 支持两种来源,优先级:特性 > 类重写
| 场景 | JobId 来源 | Expression 来源 | 说明 |
|---|---|---|---|
| 特性提供全部 | ScheduledJobAttribute.JobId |
ScheduledJobAttribute.Expression |
类无需重写 |
| 特性仅提供 JobId | 特性 | 类重写 | Expression = null 时回退到类属性 |
| 特性仅提供 Expression | 类重写 | 特性 | [ScheduledJob(Expression = "...")] |
| 无特性 | 类重写 | 类重写 | 类必须同时提供两者 |
| 均未提供 | - | - | 启动时跳过并警告 |
// 示例:特性提供 JobId,Expression 从类属性读取
[ScheduledJob("MyJob")]
public class MyJob : BaseJob
{
public override string Expression => "0/10 * * * * ?";
public override async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
await Task.CompletedTask;
}
}
TaskInterval 间隔类型
| 枚举值 | 方法 | Expression 格式 | 说明 |
|---|---|---|---|
SEC |
AddTask |
"10" 或 "5,10,15" |
按秒触发,支持每轮不同间隔 |
RunOnDay |
AddTaskRunOnDay |
"20:00:00" |
每天固定时间 |
RunOnWeek |
AddTaskRunOnWeek |
"1:20:00:00" |
周几:时:分:秒 |
RunOnMonth |
AddTaskRunOnMonth |
"1:20:00:00" 或 "-1:20:00:00" |
日:时:分:秒,负数为倒数第N天 |
Custom |
AddTaskCustom |
CRON 表达式 | 默认方式,基于 Cronos 解析 |
Round 循环次数
// 执行 10 次后自动停止(默认 -1 永久循环)
[ScheduledJob("MyJob", TaskInterval = TaskInterval.SEC, Expression = "5", Round = 10)]
配置项
SchedulerConfig
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
Redis |
RedisConfig |
- | Redis 连接配置 |
SchedulerKey |
string |
"Jobs:Scheduler" |
Redis Hash 存储键名 |
InjectionScheduler |
bool |
false |
是否注入 IScheduler 到 DI 容器 |
TimeZoneOffsetHours |
int? |
8 |
时区偏移小时数 |
AutoClean |
AutoCleanLogConfig |
- | 自动清理日志配置 |
RedisConfig
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ConnectionString |
string |
- | 主节点连接字符串 / Sentinel 连接参数 |
Mode |
RedisMode |
Single |
连接模式:Single/Cluster/Sentinel/MasterSlave |
Hosts |
string[]? |
null |
集群节点或哨兵节点地址列表 |
MasterName |
string? |
null |
哨兵监控的 master 名称(仅 Sentinel) |
ReadWriteSeparate |
bool |
false |
读写分离(仅 Sentinel) |
Slaves |
string[]? |
null |
从节点地址列表(仅 MasterSlave) |
AutoCleanLogConfig
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
Enabled |
bool |
false |
是否启用自动清理 |
Expression |
string |
"0 0 0 1 * ?" |
清理任务 CRON 表达式 |
CleanBeforeMin |
int |
1440 |
清理多少分钟前的日志(默认 24 小时) |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- Cronos (>= 0.11.1)
- FreeScheduler (>= 2.1.5)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Logging (>= 8.0.0)
-
net10.0
- Cronos (>= 0.11.1)
- FreeScheduler (>= 2.1.5)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging (>= 10.0.0)
-
net8.0
- Cronos (>= 0.11.1)
- FreeScheduler (>= 2.1.5)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Logging (>= 8.0.0)
-
net9.0
- Cronos (>= 0.11.1)
- FreeScheduler (>= 2.1.5)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Logging (>= 9.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.