Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

.net Core Development Windows Services how to use Quartz to perform scheduled tasks

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces ".NET Core development of Windows services how to use Quartz to perform timed tasks". In daily operations, I believe many people have doubts about how to use Quartz to perform timed tasks in .NET Core development of Windows services. Xiaobian consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of ".NET Core development Windows services how to use Quartz to perform timed tasks". Next, please follow the editor to study!

Recent projects also focus on providing API interfaces for teams, mostly dealing with routine business logic. In the process, there is a requirement that you need to perform some push message tasks at a fixed time every day. I wrote the scheduled tasks into the API project without much thought at the beginning. After deployment, I was stupid, the log did not show any trace of the task, and there was nothing wrong with debugging. Looking back, IIS, a lazy thing, should have gone dormant and recycled my tasks directly. Calmly, I sorted out my thoughts and checked the plan. I can change the IIS setting to modify the mode of timing recovery. I can wake up by visiting the site. I feel that it is not very appropriate. Since it is WindowsServer, it would be better for me to get a WindowsService to execute tasks regularly. Moreover, I have never written WindowsService with .net core before, so I happen to eat a crab.

At first, I directly set up a console program to write it in the way the .NET Framework was written before. It was later discovered that the .NET Core designed a project template specifically for this background service (a long-running service), called Worker Service. In order to meet the requirement of execution at a fixed time of day, the old Quartz is selected here. Briefly describe the requirements to be implemented by Demo: sending information to an API interface at a fixed point every day.

Create the project using Visual Studio (the VS2019 I use), select Worker Service (figure below), and name it WindowsServiceDemo.

After the project is created, the content is simple: a Program.cs and another Work.cs,Work class inherit BackgroundService and override its ExecuteAsync method. Obviously, the ExecuteAsync method is the entry point for performing background tasks.

In Program.cs, it is still typed by creating an IHost and starting the run. To facilitate dependency injection, you can create an extension method of IServiceCollection to register the service, which is described step by step.

Before registering for the service, install the packages that need to be referenced through Nuget. Install Quartz to perform tasks on a regular basis. In addition, because the requirement needs to call the api interface, that is, you need to use HttpClient to send the request, so you also need to introduce the package Microsoft.Extentsions.Http. Because you need to deploy as WindowService, you need to introduce the package Microsoft.Extensions.Hosting.WindowsServices.

First define the Job, that is, the specific business logic that performs the task. Create a SendMsgJob class that inherits the IJob interface and implements the Execute method. The Execute method is the method that is executed at a set point in time. This is the process of using a registered HttpClient to send a message.

Public class SendMsgJob: IJob {private readonly AppSettings _ appSettings; private const string ApiClientName = "ApiClient"; private readonly IHttpClientFactory _ httpClientFactory; private readonly ILogger _ logger; public SendMsgJob (IHttpClientFactory httpClientFactory, IOptions appSettings, ILogger logger) {_ httpClientFactory = httpClientFactory; _ logger = logger; _ appSettings = appSettings.Value } / public async Task Execute (IJobExecutionContext context) {_ logger.LogInformation ($"start executing scheduled tasks"); / / get our registered named-HttpClient using var client from httpClientFactory = _ httpClientFactory.CreateClient (ApiClientName) Var message = new {title = "message of Today", content = _ appSettings.MessageNeedToSend}; / / send message var response = await client.PostAsync ("/ msg", new JsonContent (message)); if (response.IsSuccessStatusCode) {_ logger.LogInformation ($"message sent successfully");}

Once the Job is created, you can set it to execute on a regular basis. When you come to Work.cs, replace the default demo code and configure the code for Job enforcement policy instead. Configuring Job using Quartz is roughly divided into these parts

Create a scheduler Scheduler

Create a Job instance

Create triggers to control the execution policy of Job

Pair the Job instance and trigger instance to register with the scheduler

Start the scheduler

Public class Worker: BackgroundService {private readonly ILogger _ logger; public Worker (ILogger logger) {_ logger = logger;} protected override async Task ExecuteAsync (CancellationToken stoppingToken) {_ logger.LogInformation ("service startup"); / / create a scheduler var scheduler = await StdSchedulerFactory.GetDefaultScheduler (stoppingToken) / / create Job var sendMsgJob = JobBuilder.Create () WithIdentity (nameof (SendMsgJob), nameof (Worker)) Build () / / create trigger var sendMsgTrigger = TriggerBuilder.Create () WithIdentity ("trigger-" + nameof (SendMsgJob), "trigger-group-" + nameof (Worker)) StartNow () WithSchedule (CronScheduleBuilder.DailyAtHourAndMinute (08,30)) / / execute Build () at 08:30 every day; await scheduler.Start (stoppingToken) / / put Job and trigger into the scheduler await scheduler.ScheduleJob (sendMsgJob, sendMsgTrigger, stoppingToken);}}

The configuration of the scheduled task is over, and then register the required services with the service container. Based on what we said earlier, we create an extension method to manage the services we need to register.

Public static class DependencyInject {/ define extension method, register service / public static IServiceCollection AddMyServices (this IServiceCollection services, IConfiguration config) {/ / profile services.Configure (config) / / register named HttpClient and configure the interceptor services.AddHttpClient ("ApiClient", client = > {client.BaseAddress = new Uri (config ["ApiBaseUrl"]);}) .AddHttpMessageHandler (_ = > new AuthenticRequestDelegatingHandler ()); / / register task services.AddSingleton (); return services;}}

Modify Program.cs and call the new extension method

Namespace WindowsServiceDemo {public class Program {public static void Main (string [] args) {CreateHostBuilder (args) .Build () .Run () } public static IHostBuilder CreateHostBuilder (string [] args) = > Host.CreateDefaultBuilder (args) ConfigureServices ((hostContext, services) = > {/ / Registration Service services.AddMyServices (hostContext.Configuration) AddHostedService ();});}}

At this point, the main code is introduced. For debugging, you can modify the set timing execution time (for example, after a minute) to test whether it can be successful. After modifying the trigger trigger time, run the project directly. Unfortunately, the task is not triggered regularly. What is the reason for this? In fact, although we inject our custom Job into the service container, when the scheduler creates the Job instance, it does not take it from our service container, but the scheduler uses the default instantiation. The workaround is for us to specify a JobFactory for the scheduler to rewrite the rules for instantiating the Job type.

First, create a MyJobFactory and inherit the IJobFactory interface to implement the method NewJob, which is the factory's method of instantiating Job. Here, we can rewrite the instantiation of Job into the way of getting the instance from the service container.

Namespace WindowsServiceDemo {/ Job factory, take Job / public class MyJobFactory from the service container: IJobFactory {protected readonly IServiceProvider _ serviceProvider; public MyJobFactory (IServiceProvider serviceProvider) {_ serviceProvider = serviceProvider;} public IJob NewJob (TriggerFiredBundle bundle, IScheduler scheduler) {var jobType = bundle.JobDetail.JobType Try {var job = _ serviceProvider.GetService (jobType) as IJob; return job;} catch (Exception e) {Console.WriteLine (e); throw } public void ReturnJob (IJob job) {var disposable = job as IDisposable; disposable?.Dispose ();}

The MyJobFactory is then registered with the service container, that is, added in the AddMyServices extension method

1 / / add Job Factory 2 services.AddSingleton ()

Next, replace the Factory of the scheduler with MyJobFactory, and modify the Work.cs code as follows.

Public class Worker: BackgroundService {private readonly ILogger _ logger; private readonly MyJobFactory _ jobFactory; public Worker (ILogger logger, MyJobFactory jobFactory) {_ logger = logger; _ jobFactory = jobFactory;} protected override async Task ExecuteAsync (CancellationToken stoppingToken) {_ logger.LogInformation ("service startup"); / / create a scheduler var scheduler = await StdSchedulerFactory.GetDefaultScheduler (stoppingToken) / / specify custom JobFactory scheduler.JobFactory = _ jobFactory; / / create Job var sendMsgJob = JobBuilder.Create () WithIdentity (nameof (SendMsgJob), nameof (Worker)) Build () / / create trigger var sendMsgTrigger = TriggerBuilder.Create () WithIdentity ("trigger-" + nameof (SendMsgJob), "trigger-group-" + nameof (Worker)) StartNow () WithSchedule (CronScheduleBuilder.DailyAtHourAndMinute (08,30)) / / execute Build () at 08:30 every day; await scheduler.Start (stoppingToken) / / put Job and trigger into the scheduler await scheduler.ScheduleJob (sendMsgJob, sendMsgTrigger, stoppingToken);}}

Debugging is performed here, and now once we have reached the point in time we set in the trigger, the Execute method of SendMsgJob will be triggered successfully.

After the development is complete, the remaining task is how to release the project as a WindowsService. When you come to Program.cs, you need to make some changes

Public static IHostBuilder CreateHostBuilder (string [] args) = > Host.CreateDefaultBuilder (args) .UseWindows Service () / run according to WindowsService .ConfigureServices ((hostContext, services) = > {/ / register service services.AddMyServices (hostContext.Configuration) .AddHostedService ();})

After recompiling the project successfully, we can use sc.exe to deploy as a windows service. Start the command line as an administrator and execute

> sc.exe create WindowsServiceDemo binPath= "D:\ workspace\ WindowsServiceDemo\ WindowsServiceDemo\ bin\ Debug\ netcoreapp3.1\ WindowsServiceDemo.exe" [SC] CreateService succeeded

At this point, open the services panel and you can see the WindowsServiceDemo service that has just been deployed.

At this point, the study on ".NET Core developing Windows services how to use Quartz to perform scheduled tasks" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report