Quartz.NET 全面解析與實(shí)戰(zhàn)指南
一、Quartz.NET 簡(jiǎn)介
Quartz.NET 是一個(gè)功能強(qiáng)大、開源的作業(yè)調(diào)度框架,源自 OpenSymphony 的 Quartz API 的 .NET 移植版本,用 C# 改寫,適用于 Winform、ASP.NET 以及 ASP.NET Core 等各類 .NET 應(yīng)用。它的核心能力可以概括為:在指定的時(shí)間或按照指定的周期性地執(zhí)行任務(wù)——無(wú)論是每天早上 8 點(diǎn)發(fā)送一封匯總郵件、每隔 10 分鐘輪詢一次接口狀態(tài),還是在工作日的特定時(shí)段內(nèi)執(zhí)行數(shù)據(jù)同步。
Quartz.NET 的主要特性包括:
- 支持 Cron 表達(dá)式,實(shí)現(xiàn)靈活的日歷化調(diào)度
- 持久化任務(wù)信息到數(shù)據(jù)庫(kù),避免應(yīng)用重啟后任務(wù)丟失
- 分布式集群部署,支持負(fù)載均衡與故障轉(zhuǎn)移
- 動(dòng)態(tài)管理任務(wù),支持添加、暫停、恢復(fù)、刪除作業(yè)
- 深度集成 ASP.NET Core 依賴注入系統(tǒng)
- 支持插件和監(jiān)聽器,可自定義調(diào)度邏輯和監(jiān)控機(jī)制
版本說明:Quartz.NET 3.0 是一個(gè)重大更新,引入了完整的
async/await支持,并對(duì) .NET Core 提供了原生支持,NuGet 包也進(jìn)行了拆分,例如Quartz.Jobs、Quartz.Plugins等成為獨(dú)立的依賴項(xiàng)。
二、核心概念與架構(gòu)
核心組件
| 組件 | 描述 |
|---|---|
| Job(作業(yè)) | 實(shí)現(xiàn) IJob 接口的類,包含具體要執(zhí)行的業(yè)務(wù)邏輯 |
| Trigger(觸發(fā)器) | 定義任務(wù)何時(shí)執(zhí)行的規(guī)則,如時(shí)間間隔、Cron 表達(dá)式等 |
| Scheduler(調(diào)度器) | 核心引擎,負(fù)責(zé)管理和協(xié)調(diào) Job 與 Trigger 的執(zhí)行 |
| JobStore(作業(yè)存儲(chǔ)) | 存儲(chǔ)作業(yè)和觸發(fā)器信息,支持內(nèi)存和數(shù)據(jù)庫(kù)兩種模式 |
| ThreadPool(線程池) | 為任務(wù)執(zhí)行提供線程資源 |
基本工作流程
- 定義 Job(實(shí)現(xiàn)
IJob接口的類),編寫業(yè)務(wù)邏輯 - 創(chuàng)建 Trigger,設(shè)定觸發(fā)規(guī)則(時(shí)間間隔、Cron 表達(dá)式等)
- 通過 Scheduler 將 Job 和 Trigger 綁定并啟動(dòng)調(diào)度
- 調(diào)度器按照 Trigger 的規(guī)則,在適當(dāng)?shù)臅r(shí)機(jī)通過線程池執(zhí)行 Job
3.x 的核心變化:全面異步化
從 3.0 版本開始,Quartz.NET 全面擁抱異步編程。IJob 的 Execute 方法現(xiàn)在返回 Task,可以輕松包含 async 代碼:
// 3.x 的 Job 定義
public class MyJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
// 異步操作示例
await Task.Delay(1);
}
}
如果你沒有任何異步邏輯,也可以直接返回 Task.CompletedTask。
三、快速安裝與配置
1. 安裝 NuGet 包
# 核心包 dotnet add package Quartz # ASP.NET Core 托管集成 dotnet add package Quartz.Extensions.Hosting # 如需持久化支持(例如 SQL Server) dotnet add package Quartz.Plugins dotnet add package Quartz.Serialization.Json
2. 定義 Job 類
using Quartz;
public class HelloJob : IJob
{
private readonly ILogger<HelloJob> _logger;
public HelloJob(ILogger<HelloJob> logger)
{
_logger = logger;
}
public Task Execute(IJobExecutionContext context)
{
_logger.LogInformation("Hello! 當(dāng)前時(shí)間: {Time}", DateTime.Now);
return Task.CompletedTask;
}
}Quartz.NET 通過 IJobExecutionContext 向作業(yè)傳遞上下文信息,其中包括 JobDataMap,可以在 Trigger 或 Scheduler 級(jí)別傳遞參數(shù)給 Job。
3. 注冊(cè) Quartz 到 DI 容器
在 Program.cs 中完成注冊(cè):
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddQuartz(q =>
{
// 注冊(cè) Job
var jobKey = new JobKey("HelloJob");
q.AddJob<HelloJob>(opts => opts.WithIdentity(jobKey));
// 注冊(cè)觸發(fā)器 - SimpleSchedule 方式
q.AddTrigger(opts => opts
.ForJob(jobKey)
.WithIdentity("HelloJob-trigger")
.WithSimpleSchedule(x => x.WithIntervalInSeconds(10).RepeatForever()));
});
// 添加 Quartz 托管服務(wù),隨應(yīng)用生命周期啟停
builder.Services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
var app = builder.Build();
app.Run();四、觸發(fā)器(Trigger)詳解
Trigger 是 Quartz.NET 中最靈活的組件之一,定義了作業(yè)何時(shí)執(zhí)行。
1. SimpleSchedule —— 簡(jiǎn)單間隔調(diào)度
適用于"每隔 N 秒/分鐘/小時(shí)執(zhí)行一次"這類固定間隔的場(chǎng)景:
q.AddTrigger(opts => opts
.ForJob("HelloJob")
.WithIdentity("simple-trigger")
.WithSimpleSchedule(x => x
.WithIntervalInMinutes(30) // 每 30 分鐘執(zhí)行
.RepeatForever())); // 無(wú)限重復(fù)
還可以控制重復(fù)次數(shù)、開始時(shí)間和結(jié)束時(shí)間:x.WithRepeatCount(10) 表示總共執(zhí)行 10 次后停止。
2. CronSchedule —— Cron 表達(dá)式調(diào)度
當(dāng)需要日歷化的復(fù)雜調(diào)度規(guī)則時(shí)(如"每個(gè)工作日早上 9 點(diǎn)"),使用 Cron 表達(dá)式:
q.AddTrigger(opts => opts
.ForJob("HelloJob")
.WithIdentity("cron-trigger")
.WithCronSchedule("0 0 9 ? * MON-FRI")); // 工作日早上9點(diǎn)
3. Cron 表達(dá)式詳解
Quartz.NET 使用 7 字段(年可選)的 Cron 表達(dá)式:
| 字段 | 是否必填 | 允許值 | 允許的特殊字符 |
|---|---|---|---|
| 秒 | 是 | 0-59 | , - * / |
| 分 | 是 | 0-59 | , - * / |
| 小時(shí) | 是 | 0-23 | , - * / |
| 日期 | 是 | 1-31 | , - * ? / L W |
| 月份 | 是 | 1-12 或 JAN-DEC | , - * / |
| 星期 | 是 | 1-7 或 SUN-SAT | , - * ? / L # |
| 年 | 否 | 空或 1970-2099 | , - * / |
例如 0 0 12 ? * WED 表示"每周三中午 12:00 執(zhí)行"。
常用特殊字符:
| 字符 | 含義 | 示例 |
|---|---|---|
* | 所有值 | * * * * * ? 表示每秒 |
? | 不指定值(日期和星期互斥) | 日期字段為 ? 時(shí)不關(guān)心具體日期 |
- | 范圍 | MON-FRI 表示周一至周五 |
, | 列舉 | MON,WED,FRI 表示周一、三、五 |
/ | 增量 | 0/15 在分鐘字段表示每 15 分鐘,從第 0 分鐘開始 |
L | 最后 | L 在日期字段表示當(dāng)月最后一天 |
# | 第 N 個(gè) | 6#3 在星期字段表示第 3 個(gè)周五 |
常用表達(dá)式示例:
0 0/5 * * * ? # 每 5 分鐘執(zhí)行一次 0 0 2 * * ? # 每天凌晨 2 點(diǎn)執(zhí)行 0 15 10 ? * MON-FRI # 周一至周五上午 10:15 執(zhí)行 0 0 9 ? * 6L # 每月最后一個(gè)周五上午 9 點(diǎn) 0 0/30 9-17 ? * MON-FRI # 工作日 9:00-17:00 內(nèi)每 30 分鐘執(zhí)行
4. 其他高級(jí)觸發(fā)器
Quartz.NET 還支持 DailyTimeIntervalTrigger,可以方便地定義每日時(shí)間段內(nèi)的調(diào)度:
var trigger = TriggerBuilder.Create()
.WithIdentity("officeHoursTrigger")
.WithSchedule(DailyTimeIntervalScheduleBuilder.Create()
.OnMondayThroughFriday()
.StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(9, 0))
.EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(17, 0))
.WithIntervalInHours(2))
.Build();
五、依賴注入與 Job 工廠
Quartz.NET 天然支持 ASP.NET Core 的依賴注入系統(tǒng)。創(chuàng)建帶依賴的 Job 非常簡(jiǎn)單:
// 定義有依賴注入的 Job
public class EmailJob : IJob
{
private readonly IEmailService _emailService;
public EmailJob(IEmailService emailService)
{
_emailService = emailService;
}
public async Task Execute(IJobExecutionContext context)
{
await _emailService.SendAsync("定時(shí)郵件", "來(lái)自 Quartz.NET 的問候");
}
}
// 注冊(cè)服務(wù)和 Job
builder.Services.AddTransient<IEmailService, EmailService>();
builder.Services.AddQuartz(q =>
{
q.UseMicrosoftDependencyInjectionJobFactory(); // 啟用 DI 工廠
q.AddJob<EmailJob>(opts => opts.WithIdentity("EmailJob"));
});UseMicrosoftDependencyInjectionJobFactory() 告訴 Quartz 使用 Microsoft 的 DI 容器來(lái)創(chuàng)建 Job 實(shí)例,這樣構(gòu)造函數(shù)中注入的服務(wù)就能被正確解析。
六、任務(wù)持久化(JobStore)
Quartz.NET 提供兩種存儲(chǔ)模式:
1. RAMJobStore —— 內(nèi)存存儲(chǔ)
默認(rèn)的存儲(chǔ)模式,將所有數(shù)據(jù)保存在內(nèi)存中,速度最快,但應(yīng)用停止或崩潰后任務(wù)信息會(huì)丟失。適合測(cè)試環(huán)境或不在意任務(wù)丟失的輕量場(chǎng)景。
2. AdoJobStore —— 數(shù)據(jù)庫(kù)持久化
將 Jobs 和 Triggers 存儲(chǔ)到關(guān)系型數(shù)據(jù)庫(kù)中,確保任務(wù)在應(yīng)用重啟后不會(huì)丟失,也是集群部署的基礎(chǔ)。
配置步驟:
(1)首先創(chuàng)建數(shù)據(jù)庫(kù)表——官方提供了 SQL 建表腳本,位于 database/dbtables 目錄下,所有表默認(rèn)以 QRTZ_ 為前綴。
(2)配置連接字符串和 JobStore:
Quartz.NET 4.1 及以上版本支持使用 appsettings.json 進(jìn)行層次化 JSON 配置,更加直觀:
{
"Quartz": {
"Scheduler": {
"InstanceName": "My Scheduler",
"InstanceId": "AUTO"
},
"ThreadPool": {
"MaxConcurrency": 10
},
"JobStore": {
"Type": "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
"DataSource": "default",
"TablePrefix": "QRTZ_"
},
"DataSource": {
"default": {
"Provider": "SqlServer",
"ConnectionString": "Server=localhost;Database=quartznet"
}
}
}
}
(3)在代碼中使用 JSON 配置:
builder.Services.AddQuartz(Configuration.GetSection("Quartz"), q =>
{
// 代碼配置可與 JSON 配置并存
});
七、監(jiān)聽器(Listeners)——AOP 式任務(wù)監(jiān)控
監(jiān)聽器是 Quartz.NET 中實(shí)現(xiàn)任務(wù)監(jiān)控和橫切關(guān)注點(diǎn)(AOP)的關(guān)鍵機(jī)制。通過實(shí)現(xiàn)監(jiān)聽器接口,可以在調(diào)度生命周期中插入自定義邏輯(如日志記錄、性能監(jiān)控、告警通知等)。
1. JobListener —— 監(jiān)聽 Job 事件
接收與 Job 執(zhí)行相關(guān)的三個(gè)事件:
public class LoggingJobListener : JobListenerSupport
{
public override string Name => "LoggingJobListener";
public override ValueTask JobToBeExecuted(IJobExecutionContext context)
{
Console.WriteLine($"Job [{context.JobDetail.Key}] 即將執(zhí)行...");
return ValueTask.CompletedTask;
}
public override ValueTask JobWasExecuted(IJobExecutionContext context,
JobExecutionException? jobException)
{
if (jobException == null)
Console.WriteLine($"Job [{context.JobDetail.Key}] 執(zhí)行成功");
else
Console.WriteLine($"Job [{context.JobDetail.Key}] 執(zhí)行失敗: {jobException.Message}");
return ValueTask.CompletedTask;
}
}2. TriggerListener —— 監(jiān)聽 Trigger 事件
接收與觸發(fā)器相關(guān)的四個(gè)事件:
public class MetricsTriggerListener : TriggerListenerSupport
{
public override string Name => "MetricsTriggerListener";
public override ValueTask TriggerFired(ITrigger trigger, IJobExecutionContext context)
{
// 觸發(fā)器觸發(fā)時(shí)記錄指標(biāo)
return ValueTask.CompletedTask;
}
public override ValueTask TriggerMisfired(ITrigger trigger)
{
// 處理錯(cuò)過觸發(fā)的情況
Console.WriteLine($"Trigger [{trigger.Key}] 錯(cuò)過觸發(fā)!");
return ValueTask.CompletedTask;
}
}> 關(guān)鍵提示
- 異常處理:確保監(jiān)聽器內(nèi)不拋出未捕獲異常,否則可能導(dǎo)致作業(yè)卡死
- 不持久化:監(jiān)聽器注冊(cè)在運(yùn)行時(shí),不會(huì)存入 JobStore,每次應(yīng)用啟動(dòng)都需重新注冊(cè)
- 使用輔助基類:繼承
JobListenerSupport或TriggerListenerSupport可以只重寫感興趣的方法
3. 注冊(cè)監(jiān)聽器
監(jiān)聽器通過 ListenerManager 注冊(cè),配合 Matcher 精確控制作用范圍:
scheduler.ListenerManager.AddJobListener(
myJobListener,
KeyMatcher<JobKey>.KeyEquals(new JobKey("myJobName", "myJobGroup")));
// 監(jiān)聽特定組的所有 Job
scheduler.ListenerManager.AddJobListener(
myJobListener,
GroupMatcher<JobKey>.GroupEquals("myJobGroup"));
// 監(jiān)聽所有 Job
scheduler.ListenerManager.AddJobListener(
myJobListener,
GroupMatcher<JobKey>.AnyGroup());八、高級(jí)特性詳解
1. 集群部署
Quartz.NET 支持多節(jié)點(diǎn)集群,實(shí)現(xiàn)負(fù)載均衡和故障轉(zhuǎn)移。集群模式下,所有節(jié)點(diǎn)共享同一個(gè)數(shù)據(jù)庫(kù)(通過 AdoJobStore),通過數(shù)據(jù)庫(kù)鎖機(jī)制確保同一個(gè) Job 不會(huì)被多個(gè)節(jié)點(diǎn)同時(shí)執(zhí)行。
配置要點(diǎn):
- 所有共享同一套數(shù)據(jù)庫(kù)和表結(jié)構(gòu)
- 設(shè)置
org.quartz.jobStore.isClustered = true - 各節(jié)點(diǎn)的線程池參數(shù)保持一致
- 確保各節(jié)點(diǎn)時(shí)鐘同步
適用場(chǎng)景:集群特性最適用于將長(zhǎng)時(shí)間運(yùn)行的計(jì)算密集型任務(wù)分布到多個(gè)節(jié)點(diǎn)執(zhí)行,實(shí)現(xiàn)負(fù)載分擔(dān)。
2. 多調(diào)度器(Multiple Schedulers)
從 Quartz.NET 4.x 開始,可以通過 AddQuartz(string name, ...) 創(chuàng)建命名調(diào)度器,實(shí)現(xiàn)工作負(fù)載隔離:
// 快速的內(nèi)存調(diào)度器(用于高頻輕量任務(wù))
builder.Services.AddQuartz("FastScheduler", q =>
{
q.UseInMemoryStore();
q.UseDefaultThreadPool(tp => tp.MaxConcurrency = 5);
q.ScheduleJob<NotificationJob>(trigger => trigger
.WithSimpleSchedule(x => x.WithIntervalInSeconds(30).RepeatForever()));
});
// 持久化的數(shù)據(jù)庫(kù)調(diào)度器(用于關(guān)鍵業(yè)務(wù)任務(wù))
builder.Services.AddQuartz("DurableScheduler", q =>
{
q.UsePersistentStore(s =>
{
s.UseSqlServer(sql => sql.ConnectionString = "your connection string");
});
q.ScheduleJob<ReportJob>(trigger => trigger
.WithCronSchedule("0 0 2 * * ?"));
});
// 單次調(diào)用啟動(dòng)所有命名調(diào)度器
builder.Services.AddQuartzHostedService(options =>
{
options.WaitForJobsToComplete = true;
});這種做法可以讓不同的調(diào)度器使用不同的存儲(chǔ)策略、線程池和配置,彼此完全隔離。
3. 動(dòng)態(tài)作業(yè)管理
通過 IScheduler 接口可以在運(yùn)行時(shí)動(dòng)態(tài)管理任務(wù):
// 動(dòng)態(tài)添加作業(yè) await scheduler.ScheduleJob(jobDetail, trigger); // 暫停作業(yè) await scheduler.PauseJob(jobKey); // 恢復(fù)作業(yè) await scheduler.ResumeJob(jobKey); // 刪除作業(yè) await scheduler.DeleteJob(jobKey); // 檢查作業(yè)是否存在 bool exists = await scheduler.CheckExists(jobKey);
4. 傳遞參數(shù) —— JobDataMap
JobDataMap 是 Quartz.NET 中向 Job 傳遞參數(shù)的機(jī)制,可以在 Trigger 定義時(shí)或 Scheduler 級(jí)別設(shè)置鍵值對(duì):
// 在 Trigger 定義時(shí)傳遞參數(shù)(示例)
q.AddTrigger(opts => opts
.ForJob("HelloJob")
.UsingJobData("RetryCount", "3")
.UsingJobData("TimeoutSeconds", "30")
.WithCronSchedule("0 0/10 * * * ?"));
生產(chǎn)建議:CronTrigger 應(yīng)顯式設(shè)置時(shí)區(qū),參數(shù)通過 JobDataMap 傳遞,任務(wù)依賴需手動(dòng)觸發(fā)或使用監(jiān)聽器實(shí)現(xiàn)。
九、Quartz.NET vs Hangfire:如何選型?
兩個(gè)框架都能實(shí)現(xiàn)定時(shí)任務(wù),但定位和適用場(chǎng)景有明顯差異:
| 維度 | Quartz.NET | Hangfire |
|---|---|---|
| 核心定位 | 企業(yè)級(jí)調(diào)度引擎 | 通用后臺(tái)任務(wù)處理框架 |
| 調(diào)度能力 | 復(fù)雜 Cron、日歷調(diào)度、時(shí)間段約束 | 基本 Cron 表達(dá)式 |
| 持久化 | 可選(RAM / 數(shù)據(jù)庫(kù)) | 默認(rèn)依賴數(shù)據(jù)庫(kù)持久化 |
| 可視化面板 | 無(wú)(需第三方如 Quartzmin) | 內(nèi)置 Dashboard |
| 集群支持 | 原生數(shù)據(jù)庫(kù)鎖機(jī)制 | 基于持久化存儲(chǔ)的任務(wù)分發(fā) |
| 學(xué)習(xí)曲線 | 較陡峭 | 較平緩 |
| 執(zhí)行精度 | 毫秒級(jí) | 秒級(jí) |
| 最佳場(chǎng)景 | 復(fù)雜調(diào)度策略、金融系統(tǒng)、企業(yè)批處理 | 可靠任務(wù)執(zhí)行、可觀測(cè)性要求高的場(chǎng)景 |
選型建議:
- Hangfire 更適合快速集成、注重任務(wù)可觀測(cè)性、需要內(nèi)置 Dashboard 的場(chǎng)景——集成簡(jiǎn)單,自帶監(jiān)控面板
- Quartz.NET 更適合需要精確、復(fù)雜調(diào)度策略的企業(yè)級(jí)系統(tǒng)——支持豐富 Cron 表達(dá)式、日歷間隔等高級(jí)調(diào)度規(guī)則,在復(fù)雜調(diào)度場(chǎng)景下更為靈活
十、最佳實(shí)踐與注意事項(xiàng)
1. Job 設(shè)計(jì)原則
- 冪等性:Job 邏輯應(yīng)設(shè)計(jì)為可安全重復(fù)執(zhí)行的,避免集群或重試場(chǎng)景下產(chǎn)生重復(fù)數(shù)據(jù)。集群模式下,重復(fù)執(zhí)行需正確配置并保障冪等性
- 輕量化:Job 的
Execute方法應(yīng)盡快完成,耗時(shí)長(zhǎng)的工作應(yīng)拆分到子任務(wù)或消息隊(duì)列中異步處理 - 異常處理:在 Execute 方法中妥善處理異常,返回適當(dāng)?shù)?
JobExecutionException以控制重試行為 - 避免線程阻塞:充分利用 async/await 避免阻塞調(diào)度線程
2. 配置建議
- 生產(chǎn)環(huán)境必須使用
AdoJobStore,避免應(yīng)用重啟導(dǎo)致任務(wù)丟失 - 合理設(shè)置線程池大?。?code>MaxConcurrency 應(yīng)根據(jù)任務(wù)特點(diǎn)和服務(wù)器資源調(diào)整,默認(rèn)為 10
- 配置
WaitForJobsToComplete:優(yōu)雅關(guān)閉時(shí)等待正在執(zhí)行的任務(wù)完成
3. 調(diào)試與排查
- 利用
LoggingJobHistoryPlugin記錄每次作業(yè)執(zhí)行歷史 - 監(jiān)聽器實(shí)現(xiàn)自定義日志和告警
- 第三方工具如 Quartzmin 或 Quartz.NetUI(基于 Vue 的定時(shí)任務(wù)管理系統(tǒng))提供可視化任務(wù)管理
4. 動(dòng)態(tài)作業(yè)管理
- 將作業(yè)配置存儲(chǔ)在數(shù)據(jù)庫(kù)或配置中心,通過代碼動(dòng)態(tài)注冊(cè)而非硬編碼
- 利用
IScheduler接口實(shí)現(xiàn)運(yùn)行時(shí)的暫停/恢復(fù)/刪除 - 慎用
StartNow()方法,避免應(yīng)用啟動(dòng)時(shí)大量任務(wù)同時(shí)執(zhí)行
十一、資源與擴(kuò)展
- 官網(wǎng):https://www.quartz-scheduler.net
- GitHub:https://github.com/quartznet/quartznet
- 文檔:https://www.quartz-scheduler.net/documentation
- 擴(kuò)展包:
Quartz.Extensions.Hosting:ASP.NET Core 托管服務(wù)。
Quartz.Serialization.SystemTextJson:JSON 序列化支持。
Quartz.Plugins:提供日志、異常處理等插件。
到此這篇關(guān)于Quartz.NET 全面解析與實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Quartz.NET全面介紹內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 在.NET6中使用配置Quartz.NET定時(shí)任務(wù)并使用IHostedService實(shí)現(xiàn)項(xiàng)目啟動(dòng)自動(dòng)加載任務(wù)
- ASP.NET?MVC使用Quartz.NET執(zhí)行定時(shí)任務(wù)
- 作業(yè)調(diào)度框架Quartz.net用法詳解
- C#定時(shí)任務(wù)框架Quartz.NET介紹與用法
- Quartz.Net使用方法詳解
- Quartz.NET的具體使用
- Quartz.Net任務(wù)和觸發(fā)器實(shí)現(xiàn)方法詳解
- 詳解.NET Core使用Quartz執(zhí)行調(diào)度任務(wù)進(jìn)階
- .net core中Quartz的使用方法
- .Net Core中使用Quartz.Net實(shí)踐記錄
- Quartz.Net調(diào)度框架配置解析
相關(guān)文章
asp.net 無(wú)法獲取的內(nèi)部?jī)?nèi)容,因?yàn)樵搩?nèi)容不是文本 的解決方法
asp.net 無(wú)法獲取的內(nèi)部?jī)?nèi)容,因?yàn)樵搩?nèi)容不是文本 的解決方法2009-12-12
.Net整合Json實(shí)現(xiàn)REST服務(wù)客戶端的方法詳解
這篇文章主要給大家介紹了關(guān)于.Net整合Json實(shí)現(xiàn)REST服務(wù)客戶端的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
asp.net文件上傳功能(單文件,多文件,自定義生成縮略圖,水印)
上傳功能,是大家經(jīng)常用到了,可能每一個(gè)項(xiàng)目都可以會(huì)用到。網(wǎng)上到處都有上傳功能的代碼。比我寫的好的有很多。我這里也僅是分享我的代碼。2011-09-09
ASP.NET堆和棧四之對(duì)托管和非托管資源的垃圾回收和內(nèi)存分配
這篇文章介紹了.NET堆和棧中對(duì)托管和非托管資源的垃圾回收和內(nèi)存分配,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
在GridView中LinkButton的屬性的應(yīng)用(如何不用選中就刪除這一行)
GridView中LinkButton的屬性的應(yīng)用,實(shí)現(xiàn)不用選中就刪除這一行2009-04-04
詳解可跨域的單點(diǎn)登錄(SSO)實(shí)現(xiàn)方案【附.net代碼】
本篇文章主要介紹了可跨域的單點(diǎn)登錄(SSO)實(shí)現(xiàn)方案,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2016-11-11
SqlCommandBuilder如何實(shí)現(xiàn)批量更新
這篇文章主要介紹了SqlCommandBuilder如何實(shí)現(xiàn)批量更新,需要的朋友可以參考下2015-10-10

