SMEAppHouse.Core.QuartzExt
10.0.0
dotnet add package SMEAppHouse.Core.QuartzExt --version 10.0.0
NuGet\Install-Package SMEAppHouse.Core.QuartzExt -Version 10.0.0
<PackageReference Include="SMEAppHouse.Core.QuartzExt" Version="10.0.0" />
<PackageVersion Include="SMEAppHouse.Core.QuartzExt" Version="10.0.0" />
<PackageReference Include="SMEAppHouse.Core.QuartzExt" />
paket add SMEAppHouse.Core.QuartzExt --version 10.0.0
#r "nuget: SMEAppHouse.Core.QuartzExt, 10.0.0"
#:package SMEAppHouse.Core.QuartzExt@10.0.0
#addin nuget:?package=SMEAppHouse.Core.QuartzExt&version=10.0.0
#tool nuget:?package=SMEAppHouse.Core.QuartzExt&version=10.0.0
SMEAppHouse.Core.QuartzExt
Overview
SMEAppHouse.Core.QuartzExt is an extension library for implementing Quartz scheduling services. It provides base classes and utilities for creating scheduled jobs using the Quartz.NET scheduler with a simplified API and singleton pattern support.
Target Framework: .NET 8.0
Namespace: SMEAppHouse.Core.QuartzExt
Public Classes and Interfaces
1. Job Service Base Classes
JobServiceBase<T>
Abstract base class for Quartz job services implementing the Curiously Recurring Template Pattern (CRTP) for singleton behavior.
Namespace: SMEAppHouse.Core.QuartzExt
Implements: IJobService
Key Features:
- Singleton pattern via static
Instanceproperty - Thread-safe execution with mutex locks
- Prevents concurrent execution of the same job
Key Properties:
Static Instance
public static T Instance { get; }
Returns the singleton instance of the job service. Creates and initializes the instance on first access.
Key Methods:
Abstract Methods (Must Implement)
public abstract void SubscriberInitialize()
public abstract void SubscriberExecute()
Execute
public void Execute(ThreadPriority? threadPrio = ThreadPriority.Normal)
Executes the job service in a separate thread with optional thread priority. Prevents concurrent execution.
Example:
using SMEAppHouse.Core.QuartzExt;
public class DataSyncJob : JobServiceBase<DataSyncJob>
{
public override void SubscriberInitialize()
{
// Called once when instance is created
Console.WriteLine("DataSyncJob initialized");
// Initialize resources, connections, etc.
}
public override void SubscriberExecute()
{
// Called each time the job executes
Console.WriteLine($"DataSyncJob executing at {DateTime.Now}");
try
{
// Your job logic here
SyncData();
}
catch (Exception ex)
{
Console.WriteLine($"Error in DataSyncJob: {ex.Message}");
}
}
private void SyncData()
{
// Data synchronization logic
}
}
// Usage - Get singleton instance
var job = DataSyncJob.Instance;
// Execute manually (optional - usually called by Quartz scheduler)
job.Execute(ThreadPriority.Normal);
JobServiceMemberBase<T>
Base class for job service members that can run as background threads.
Namespace: SMEAppHouse.Core.QuartzExt
Implements: IJobServiceMember
Key Properties:
bool AsBackground- Run as background threadbool AutoRun- Automatically start on constructionbool Success- Execution success statusException Exception- Exception if execution failedbool Executing- Whether currently executingThread InstanceThread- The thread instanceAction InstanceAction- Action to execute
Key Methods:
public virtual void ExecuteInstance()
public void Start()
public void DestroySelf()
Events:
SelfDestroyerDelegate OnSelfDestructNow- Raised when destroying the instance
Example:
public class BackgroundWorker : JobServiceMemberBase<BackgroundWorker>
{
public BackgroundWorker() : base()
{
AsBackground = true;
AutoRun = false;
InstanceAction = DoWork;
}
public override void ExecuteInstance()
{
base.ExecuteInstance();
try
{
InstanceAction?.Invoke();
Success = true;
}
catch (Exception ex)
{
Exception = ex;
Success = false;
}
}
private void DoWork()
{
// Background work logic
}
}
// Usage
var worker = new BackgroundWorker();
worker.Start();
2. Job Service Starter
JobServiceStarter<T>
Static helper class for starting Quartz scheduled jobs.
Namespace: SMEAppHouse.Core.QuartzExt
Key Methods:
Start
public static async void Start(
int recurrenceInterval = 60,
Rules.TimeIntervalTypesEnum intervalType = Rules.TimeIntervalTypesEnum.Seconds,
string jobGroupName = "",
string triggerGroupName = "")
Starts a Quartz scheduler for the specified job service type.
Parameters:
recurrenceInterval- Interval between job executions (default: 60)intervalType- Type of interval (Seconds, Minutes, Hours, Days, etc.)jobGroupName- Optional job group nametriggerGroupName- Optional trigger group name
Example:
using SMEAppHouse.Core.QuartzExt;
using SMEAppHouse.Core.CodeKits;
// Start job to run every 5 minutes
JobServiceStarter<DataSyncJob>.Start(
recurrenceInterval: 5,
intervalType: Rules.TimeIntervalTypesEnum.Minutes
);
// Start job to run every 30 seconds
JobServiceStarter<DataSyncJob>.Start(
recurrenceInterval: 30,
intervalType: Rules.TimeIntervalTypesEnum.Seconds
);
// Start job to run every hour
JobServiceStarter<DataSyncJob>.Start(
recurrenceInterval: 1,
intervalType: Rules.TimeIntervalTypesEnum.Hours
);
// Start job with custom group names
JobServiceStarter<DataSyncJob>.Start(
recurrenceInterval: 10,
intervalType: Rules.TimeIntervalTypesEnum.Minutes,
jobGroupName: "SyncJobs",
triggerGroupName: "SyncTriggers"
);
JobServiceInstance<TJobSvc>
Internal Quartz job wrapper that executes the job service.
Namespace: SMEAppHouse.Core.QuartzExt (nested in JobServiceStarter<T>)
Implements: IJob
Properties:
JobServiceBase<TJobSvc> Instance- The job service instance
Methods:
public Task Execute(IJobExecutionContext context)
This class is used internally by Quartz to execute the job service.
3. Interfaces
IJobService
Interface for job services.
Namespace: SMEAppHouse.Core.QuartzExt
Methods:
void Execute(ThreadPriority? threadPrio = ThreadPriority.Normal)
void SubscriberInitialize()
void SubscriberExecute()
IJobServiceMember
Interface for job service members.
Namespace: SMEAppHouse.Core.QuartzExt
Properties:
bool AsBackgroundbool AutoRunbool SuccessException Exceptionbool ExecutingThread InstanceThread
Methods:
void Start()
void ExecuteInstance()
void DestroySelf()
4. Time Interval Types
The library uses Rules.TimeIntervalTypesEnum from SMEAppHouse.Core.CodeKits:
MilliSeconds- MillisecondsSeconds- SecondsMinutes- MinutesHours- HoursDays- DaysMonths- MonthsYears- Years
Complete Usage Examples
Example 1: Simple Scheduled Job
using SMEAppHouse.Core.QuartzExt;
using SMEAppHouse.Core.CodeKits;
public class EmailNotificationJob : JobServiceBase<EmailNotificationJob>
{
public override void SubscriberInitialize()
{
// Initialize email service, database connections, etc.
Console.WriteLine("EmailNotificationJob initialized");
}
public override void SubscriberExecute()
{
try
{
Console.WriteLine($"Checking for pending emails at {DateTime.Now}");
// Get pending emails from database
var pendingEmails = GetPendingEmails();
foreach (var email in pendingEmails)
{
SendEmail(email);
MarkAsSent(email);
}
Console.WriteLine($"Processed {pendingEmails.Count} emails");
}
catch (Exception ex)
{
Console.WriteLine($"Error in EmailNotificationJob: {ex.Message}");
// Log error
}
}
private List<Email> GetPendingEmails()
{
// Database query logic
return new List<Email>();
}
private void SendEmail(Email email)
{
// Email sending logic
}
private void MarkAsSent(Email email)
{
// Update database
}
}
// In your application startup (e.g., Program.cs or Startup.cs)
public void ConfigureServices(IServiceCollection services)
{
// Start the job to run every 2 minutes
JobServiceStarter<EmailNotificationJob>.Start(
recurrenceInterval: 2,
intervalType: Rules.TimeIntervalTypesEnum.Minutes
);
}
Example 2: Multiple Scheduled Jobs
public class DataBackupJob : JobServiceBase<DataBackupJob>
{
public override void SubscriberInitialize()
{
Console.WriteLine("DataBackupJob initialized");
}
public override void SubscriberExecute()
{
Console.WriteLine($"Running backup at {DateTime.Now}");
PerformBackup();
}
private void PerformBackup()
{
// Backup logic
}
}
public class HealthCheckJob : JobServiceBase<HealthCheckJob>
{
public override void SubscriberInitialize()
{
Console.WriteLine("HealthCheckJob initialized");
}
public override void SubscriberExecute()
{
Console.WriteLine($"Health check at {DateTime.Now}");
CheckSystemHealth();
}
private void CheckSystemHealth()
{
// Health check logic
}
}
// Start multiple jobs
public void StartAllJobs()
{
// Backup every 6 hours
JobServiceStarter<DataBackupJob>.Start(
recurrenceInterval: 6,
intervalType: Rules.TimeIntervalTypesEnum.Hours
);
// Health check every 30 seconds
JobServiceStarter<HealthCheckJob>.Start(
recurrenceInterval: 30,
intervalType: Rules.TimeIntervalTypesEnum.Seconds
);
}
Example 3: Job with Resource Management
public class DatabaseCleanupJob : JobServiceBase<DatabaseCleanupJob>
{
private IDbConnection _connection;
private bool _disposed = false;
public override void SubscriberInitialize()
{
// Initialize database connection
_connection = CreateDatabaseConnection();
Console.WriteLine("DatabaseCleanupJob initialized");
}
public override void SubscriberExecute()
{
try
{
Console.WriteLine($"Starting database cleanup at {DateTime.Now}");
// Clean up old records
CleanupOldRecords();
// Optimize tables
OptimizeTables();
Console.WriteLine("Database cleanup completed");
}
catch (Exception ex)
{
Console.WriteLine($"Error during cleanup: {ex.Message}");
throw;
}
}
private void CleanupOldRecords()
{
// Cleanup logic using _connection
}
private void OptimizeTables()
{
// Optimization logic
}
private IDbConnection CreateDatabaseConnection()
{
// Create and return connection
return null; // Placeholder
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_connection?.Dispose();
}
_disposed = true;
}
}
}
Example 4: Job with Configuration
public class ReportGenerationJob : JobServiceBase<ReportGenerationJob>
{
private readonly IConfiguration _configuration;
private string _reportPath;
public ReportGenerationJob()
{
// Note: In a real scenario, you might use dependency injection
// For singleton pattern, you may need to access configuration differently
}
public override void SubscriberInitialize()
{
// Load configuration
_reportPath = GetReportPath();
Console.WriteLine($"ReportGenerationJob initialized. Output path: {_reportPath}");
}
public override void SubscriberExecute()
{
try
{
var reportDate = DateTime.Now;
Console.WriteLine($"Generating report for {reportDate:yyyy-MM-dd}");
var report = GenerateReport(reportDate);
SaveReport(report, reportDate);
Console.WriteLine("Report generated successfully");
}
catch (Exception ex)
{
Console.WriteLine($"Error generating report: {ex.Message}");
}
}
private Report GenerateReport(DateTime date)
{
// Report generation logic
return new Report();
}
private void SaveReport(Report report, DateTime date)
{
var filename = Path.Combine(_reportPath, $"report_{date:yyyyMMdd}.pdf");
// Save report logic
}
private string GetReportPath()
{
// Get from configuration or default
return @"C:\Reports";
}
}
// Start job to run daily at specific interval
JobServiceStarter<ReportGenerationJob>.Start(
recurrenceInterval: 24,
intervalType: Rules.TimeIntervalTypesEnum.Hours
);
Example 5: Manual Execution (Without Scheduler)
public class OnDemandJob : JobServiceBase<OnDemandJob>
{
public override void SubscriberInitialize()
{
Console.WriteLine("OnDemandJob initialized");
}
public override void SubscriberExecute()
{
Console.WriteLine("Executing on-demand job");
ProcessOnDemand();
}
private void ProcessOnDemand()
{
// Processing logic
}
}
// Execute manually without Quartz scheduler
public void ExecuteManually()
{
var job = OnDemandJob.Instance;
// Execute with normal priority
job.Execute();
// Or execute with high priority
job.Execute(ThreadPriority.Highest);
}
Example 6: Job Service Member Usage
public class BackgroundProcessor : JobServiceMemberBase<BackgroundProcessor>
{
private Queue<WorkItem> _workQueue = new();
public BackgroundProcessor() : base()
{
AsBackground = true;
AutoRun = true; // Start automatically
InstanceAction = ProcessWorkQueue;
}
public override void ExecuteInstance()
{
base.ExecuteInstance();
try
{
InstanceAction?.Invoke();
Success = true;
}
catch (Exception ex)
{
Exception = ex;
Success = false;
Console.WriteLine($"Error: {ex.Message}");
}
}
private void ProcessWorkQueue()
{
while (_workQueue.Count > 0)
{
var item = _workQueue.Dequeue();
ProcessItem(item);
}
}
public void Enqueue(WorkItem item)
{
_workQueue.Enqueue(item);
}
private void ProcessItem(WorkItem item)
{
// Process work item
}
}
// Usage
var processor = new BackgroundProcessor(); // Auto-starts
processor.Enqueue(new WorkItem());
Key Features
- Singleton Pattern: Automatic singleton management via CRTP
- Thread Safety: Mutex locks prevent concurrent execution
- Quartz Integration: Seamless integration with Quartz.NET scheduler
- Flexible Scheduling: Support for various time intervals (seconds, minutes, hours, days, etc.)
- Background Execution: Jobs run in separate threads
- Lifecycle Management: Initialize and execute methods for proper resource management
- Error Handling: Built-in exception handling in execution flow
Dependencies
- Quartz (v3.15.0)
- SMEAppHouse.Core.CodeKits
Notes
- Jobs are singletons - only one instance exists per job type
SubscriberInitialize()is called once when the instance is first createdSubscriberExecute()is called each time the job runs- Use
JobServiceStarter<T>.Start()to schedule jobs with Quartz - Jobs can also be executed manually via
Instance.Execute() - Thread priority can be specified for manual execution
- The scheduler uses binary serialization by default
- Job and trigger names are auto-generated based on the job type name
- Custom group names can be specified for organization
License
Copyright © Nephiora IT Solutions 2025
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- Quartz (>= 3.15.1)
- SMEAppHouse.Core.CodeKits (>= 10.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.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.0 | 115 | 2/25/2026 |
| 9.0.9 | 135 | 11/29/2025 |
| 9.0.8 | 131 | 11/29/2025 |
| 9.0.7 | 131 | 11/29/2025 |
| 1.4.1906.15 | 961 | 6/12/2019 |
| 1.4.1906.14 | 839 | 6/9/2019 |
| 1.4.1811.9 | 918 | 11/9/2018 |
| 1.3.18073.3 | 915 | 11/6/2018 |
release notes