So planen Sie Jobs mit Quartz.NET in ASP.NET Core

Wenn Sie an Webanwendungen arbeiten, müssen Sie häufig bestimmte Aufgaben im Hintergrund ausführen. In einigen Fällen sind dies Aufgaben, die in vordefinierten Zeitintervallen ausgeführt werden sollten.

Quartz.NET ist ein Open Source .NET-Port des beliebten Java Job Scheduling Framework. Es wird seit langer Zeit verwendet und bietet eine hervorragende Unterstützung für die Arbeit mit Cron-Ausdrücken. Weitere Informationen zu Quartz.NET finden Sie in einem früheren Beitrag hier. 

Dieser Artikel enthält eine Diskussion darüber, wie wir mit Quartz.NET in ASP.NET Core arbeiten können, um Hintergrundjobs zu planen.

Um mit den in diesem Artikel bereitgestellten Codebeispielen arbeiten zu können, muss Visual Studio 2019 auf Ihrem System installiert sein. Wenn Sie noch keine Kopie haben, können Sie Visual Studio 2019 hier herunterladen. 

Erstellen Sie ein ASP.NET Core API-Projekt

Zunächst erstellen wir ein ASP.NET Core-Projekt in Visual Studio. Angenommen, Visual Studio 2019 ist auf Ihrem System installiert, führen Sie die folgenden Schritte aus, um ein neues ASP.NET Core-Projekt in Visual Studio zu erstellen.

  1. Starten Sie die Visual Studio-IDE.
  2. Klicken Sie auf "Neues Projekt erstellen".
  3. Wählen Sie im Fenster "Neues Projekt erstellen" aus der Liste der angezeigten Vorlagen "ASP.NET Core-Webanwendung" aus.
  4. Weiter klicken.
  5. Geben Sie im nächsten Fenster "Konfigurieren Sie Ihr neues Projekt" den Namen und den Speicherort für das neue Projekt an.
  6. Klicken Sie auf Erstellen.
  7. Wählen Sie im Fenster "Neue ASP.NET Core-Webanwendung erstellen" .NET Core als Laufzeit und ASP.NET Core 2.2 (oder höher) aus der Dropdown-Liste oben aus. Ich werde hier ASP.NET Core 3.0 verwenden.
  8. Wählen Sie "API" als Projektvorlage aus, um eine neue ASP.NET Core API-Anwendung zu erstellen. 
  9. Stellen Sie sicher, dass die Kontrollkästchen "Docker-Unterstützung aktivieren" und "Für HTTPS konfigurieren" deaktiviert sind, da diese Funktionen hier nicht verwendet werden.
  10. Stellen Sie sicher, dass die Authentifizierung auf "Keine Authentifizierung" eingestellt ist, da wir auch keine Authentifizierung verwenden.
  11. Klicken Sie auf Erstellen. 

Dadurch wird ein neues ASP.NET Core API-Projekt in Visual Studio erstellt. Wählen Sie im Projektmappen-Explorer den Lösungsordner "Controller" aus und klicken Sie auf "Hinzufügen -> Controller ...", um einen neuen Controller mit dem Namen "DefaultController" zu erstellen.

Um mit Quartz zu arbeiten, sollten Sie als Nächstes das Quartz-Paket von NuGet installieren. Sie können dies entweder über den NuGet-Paketmanager in der Visual Studio 2019-IDE oder durch Ausführen des folgenden Befehls in der NuGet-Paketmanagerkonsole tun:

Install-Package Quartz

Quartz.NET-Jobs, Trigger und Scheduler 

Die drei Hauptkonzepte in Quartz.NET sind Jobs, Trigger und Scheduler. Ein Job enthält den Code zum Ausführen einer Aufgabe oder eines auszuführenden Jobs. Ein Job wird durch eine Klasse dargestellt, die die IJob-Schnittstelle implementiert. Ein Trigger wird verwendet, um den Zeitplan und andere Details eines Jobs anzugeben. Sie können einen Auslöser verwenden, um anzugeben, wie der Job ausgeführt werden soll. Der Scheduler ist die Komponente, die für das Abrufen und Ausführen von Jobs basierend auf vordefinierten Zeitplänen verantwortlich ist.

Erstellen Sie einen Planer mit Quartz.NET

Es ist zu beachten, dass eine Anwendung mehrere Scheduler enthalten kann. Der Einfachheit halber verwenden wir hier jedoch nur einen Scheduler. Das folgende Codefragment zeigt, wie Sie eine Scheduler-Instanz erstellen können.

var scheduler = StdSchedulerFactory.GetDefaultScheduler (). GetAwaiter (). GetResult ();

Nachdem der Scheduler erstellt wurde, können Sie den folgenden Code in der ConfigureServices-Methode der Datei Startup.cs verwenden, um die Scheduler-Instanz als Singleton-Service hinzuzufügen.

services.AddSingleton (Scheduler);

Starten und stoppen Sie einen Scheduler mit Quartz.NET

Um den Scheduler zu starten und zu stoppen, nutzen wir einen Hosting-Service. Dazu müssen Sie eine Klasse erstellen, die die IHostingService-Schnittstelle implementiert, wie im folgenden Code-Snippet gezeigt.

öffentliche Klasse CustomQuartzHostedService: IHostedService

{

        privat schreibgeschützt IScheduler _scheduler;

        public CustomQuartzHostedService (IScheduler Scheduler)

        {

            _scheduler = Scheduler;

        }}

        public async Task StartAsync (CancellationToken CancellationToken)

        {

            auf _scheduler warten? .Start (CancellationToken);

        }}

        public async Task StopAsync (CancellationToken CancellationToken)

        {

            auf _scheduler warten? .Shutdown (CancellationToken);

        }}

 }}

Beachten Sie, dass Sie den gehosteten Dienst in der Servicesammlung in der ConfigureServices-Methode mithilfe des unten angegebenen Codeausschnitts registrieren sollten.

services.AddHostedService ();

Hier ist die aktualisierte ConfigureServices-Methode als Referenz:

public void ConfigureServices (IServiceCollection-Dienste)

{

    services.AddControllers ();

    var scheduler =

    StdSchedulerFactory.GetDefaultScheduler (). GetAwaiter (). GetResult ();

    services.AddSingleton (Scheduler);

    services.AddHostedService ();

}}

Erstellen Sie einen Job mit Quartz.NET

Wie bereits erwähnt, ist ein Job eine Klasse, die die IJob-Schnittstelle implementiert und die Execute () -Methode enthält. Die Execute () -Methode akzeptiert eine Instanz vom Typ IJobExecutionContext.

Das folgende Codeausschnitt zeigt eine Jobklasse, die auch eine asynchrone Execute () -Methode enthält. Diese Methode enthält den Code, der der Aufgabe entspricht, die Ihr Job ausführen soll.

[DisallowConcurrentExecution]

öffentliche Klasse NotificationJob: IJob

    {

        privat schreibgeschützt ILogger _logger;

        public NotificationJob (ILogger-Logger)

        {

            _logger = logger;

        }}

        public Task Execute (IJobExecutionContext-Kontext)

        {

            _logger.LogInformation ("Hallo Welt!");

            return Task.CompletedTask;

        }}

    }}

Erstellen Sie eine Jobfabrik mit Quartz.NET

Eine Job Factory ist eine Klasse, die die IJobFactory-Schnittstelle erbt und die Methoden NewJob () und ReturnJob () implementiert. Mit dem folgenden Codefragment kann eine Factory-Klasse erstellt werden, mit der eine Jobinstanz erstellt und zurückgegeben werden kann.

öffentliche Klasse CustomQuartzJobFactory: IJobFactory

    {

        privat schreibgeschützt IServiceProvider _serviceProvider;

        public CustomQuartzJobFactory (IServiceProvider serviceProvider)

        {

            _serviceProvider = serviceProvider;

        }}

        public IJob NewJob (TriggerFiredBundle triggerFiredBundle,

        IScheduler Scheduler)

        {

            var jobDetail = triggerFiredBundle.JobDetail;

            return (IJob) _serviceProvider.GetService (jobDetail.JobType);

        }}

        public void ReturnJob (IJob-Job) {}

    }}

Beachten Sie, dass diese Implementierung das Job-Pooling nicht nutzt. Wenn Sie Jobpooling verwenden möchten, sollten Sie die NewJob () -Methode ändern und dann die ReturnJob () -Methode implementieren.

Erstellen Sie eine JobMetadata-Klasse, um Ihre Job-Metadaten zu speichern

Wir verwenden eine benutzerdefinierte Klasse, um die Metadaten zu speichern, die sich auf einen Job beziehen, dh die Job-ID, den Namen usw. Die folgende Klasse repräsentiert die Job-Metadatenklasse.

öffentliche Klasse JobMetadata

    {

        public Guid JobId {get; einstellen; }}

        public Type JobType {get; }}

        öffentliche Zeichenfolge JobName {get; }}

        öffentlicher String CronExpression {get; }}

        öffentliche JobMetadata (Guid-ID, Typ jobType, Zeichenfolge jobName,

        Zeichenfolge cronExpression)

        {

            JobId = Id;

            JobType = jobType;

            JobName = jobName;

            CronExpression = cronExpression;

        }}

    }}

Erstellen Sie einen gehosteten Dienst, um den Quartz.NET-Scheduler zu starten und zu stoppen

Als nächstes müssen wir einen gehosteten Dienst implementieren. Ein gehosteter Dienst ist eine Klasse, die die IHostedService-Schnittstelle implementiert und den Quartz-Scheduler startet. Die folgende Codeliste zeigt eine benutzerdefinierte gehostete Serviceklasse.

öffentliche Klasse CustomQuartzHostedService: IHostedService

    {

        privat schreibgeschützt ISchedulerFactory schedulerFactory;

        privat schreibgeschützt IJobFactory jobFactory;

        privat schreibgeschützt JobMetadata jobMetadata;

        public CustomQuartzHostedService (ISchedulerFactory

            schedulerFactory,

            JobMetadata jobMetadata,

            IJobFactory jobFactory)

        {

            this.schedulerFactory = schedulerFactory;

            this.jobMetadata = jobMetadata;

            this.jobFactory = jobFactory;

        }}

        public IScheduler Scheduler {get; einstellen; }}

        public async Task StartAsync (CancellationToken CancellationToken)

        {

            Scheduler = warte auf schedulerFactory.GetScheduler ();

            Scheduler.JobFactory = jobFactory;

            var job = CreateJob (jobMetadata);

            var trigger = CreateTrigger (jobMetadata);

            warte auf Scheduler.ScheduleJob (Job, Trigger, CancellationToken);

            warte auf Scheduler.Start (CancellationToken);

        }}

        public async Task StopAsync (CancellationToken CancellationToken)

        {

            Scheduler abwarten? .Shutdown (CancellationToken);

        }}

        privater ITrigger CreateTrigger (JobMetadata jobMetadata)

        {

            return TriggerBuilder.Create ()

            .WithIdentity (jobMetadata.JobId.ToString ())

            .WithCronSchedule (jobMetadata.CronExpression)

            .WithDescription ($ "{jobMetadata.JobName}")

            .Bauen();

        }}

        private IJobDetail CreateJob (JobMetadata jobMetadata)

        {

            JobBuilder zurückgeben

            .Create (jobMetadata.JobType)

            .WithIdentity (jobMetadata.JobId.ToString ())

            .WithDescription ($ "{jobMetadata.JobName}")

            .Bauen();

        }}

    }}

Das folgende Codefragment zeigt den vollständigen Code der ConfigureServices-Methode der Startup-Klasse.

public void ConfigureServices (IServiceCollection-Dienste)

{

services.AddControllers ();

services.AddSingleton ();

services.AddSingleton ();

services.AddSingleton ();

services.AddSingleton (neue JobMetadata (Guid.NewGuid (), typeof (NotificationJob), "Notification Job", "0/10 * * * *?"));

services.AddHostedService ();

}}

Und das ist alles was Sie tun müssen! Wenn Sie die Anwendung ausführen, werden Sie feststellen, dass die Execute () -Methode der NotificationJob-Klasse alle 10 Sekunden einmal ausgeführt wird.

Quartz.NET ist eine gute Wahl für die Implementierung von Schedulern in Ihren Anwendungen. Sie können die Persistenzfunktion in Quartz.NET nutzen, um Ihre Jobs auch in einer Datenbank wie SQL Server, PostgreSQL oder SQLite zu speichern.