使用WorkerServices和.NETCore3.1构建Windows服务

笔记

Adding the Quartz.NET hosted service
You need to do two things to register the Quartz.NET hosted service:

  • Register the Quartz.NET required services with the DI container
  • Register the hosted service

根据Quartz文档Microsoft DI Integration 中的描述,在微软的集成中,使用services.AddQuartzHostedService 将服务注册到 hosted service中 。根据源码可以看到是调用了services.AddSingleton方法,注册了一个单例生命周期的服务。

WorkerServices+Quartz+Windows服务 是否可实现?

  • 思路
    一开始以为services.AddQuartzHostedService 就已经是创建了一个服务,但是发现总是不对,问题在于没有添加 Host Service服务。而且AddQuartzHostedService 只是注册了一个单例生命周期的服务,并没有针对Windows服务做进一步的实现。没有实现OnStart 和OnStop 方法。所以一致报错。

    在后面添加上services.AddHostedService<Worker>(); 后,程序可以正常运行,本质上Quartz还是需要依托于一个正常运行的HostService 。而一个正常的Windows服务程序则必须是一个可以长时间运行的 HostService 。需要从BackgroundService派生并覆盖实现必要的部份方法

参考:

为将作为服务应用程序的一部分而存在的服务提供基类。 在创建新的服务类时,必须从 ServiceBase 类 派生。
在服务应用程序中定义服务类时从ServiceBase派生。任何有用的服务都会覆盖OnStart和OnStop方法。对于附加功能,您可以使用特定行为覆盖OnPause和OnContinue,以响应服务状态的变化。

DemoFile:

program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using Quartz;
using WorkerServiceDemoNet6;

IHost host = Host.CreateDefaultBuilder(args)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseWindowsService(option =>
{
option.ServiceName = "NET6.0 Test Windows Service";
})
.ConfigureAppConfiguration((hostingContext, configuration) =>
{
configuration.Sources.Clear();

IHostEnvironment env = hostingContext.HostingEnvironment;

Console.WriteLine("ENVIRONMENT: " + env == null ? "" : env.EnvironmentName ?? "");

configuration
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile(@"appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
})
.ConfigureServices(services =>
{
services.AddQuartz(q =>
{
q.SchedulerId = "Scheduler-Core";

q.UseInMemoryStore();
q.UseDefaultThreadPool(tp =>
{
tp.MaxConcurrency = 10;
});
//Use a Scoped container to create jobs. I'll touch on this later
q.UseMicrosoftDependencyInjectionJobFactory();

//q.AddJobAndTrigger<TestJob>(hostContext.Configuration);

// Create a "key" for the job
var jobKey = new JobKey("TestJob");
// Register the job with the DI container
q.AddJob<TestJob>(opts => opts.WithIdentity(jobKey));
// Create a trigger for the job
q.AddTrigger(opts => opts
.ForJob(jobKey) // link to the HelloWorldJob
.WithIdentity("HelloWorldJob-trigger") // give the trigger a unique name
.WithCronSchedule("0/5 * * * * ?")); // run every 5 seconds

});

//Add the Quartz.NET hosted service
services.AddQuartzHostedService(
q =>
{
q.WaitForJobsToComplete = true;
q.AwaitApplicationStarted = true;
});
})
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();

await host.RunAsync();

转载:
Create a Windows Service using BackgroundService
Building a Windows service with Worker Services and .NET Core 3.1, part 1: Introduction

Using Quartz.NET with ASP.NET Core and worker services
.NET Core Workers as Windows Services

参考:

AddTransient, AddScoped and AddSingleton Services Differences

ASP.NET Core Service Lifetimes (Infographic)

作者

zhang

发布于

2022-05-12

更新于

2023-09-19

许可协议

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×