中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

.NET Core開發Windows服務之怎么使用Quartz執行定時任務

發布時間:2021-10-19 09:31:58 來源:億速云 閱讀:192 作者:iii 欄目:編程語言

這篇文章主要介紹“.NET Core開發Windows服務之怎么使用Quartz執行定時任務”,在日常操作中,相信很多人在.NET Core開發Windows服務之怎么使用Quartz執行定時任務問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”.NET Core開發Windows服務之怎么使用Quartz執行定時任務”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

最近的項目也是主要為團隊提供API接口,大多都是處理常規的業務邏輯上的事。過程中有個需求是需要每日定時定點執行一些推送消息的任務,一開始也沒多想就將定時任務寫到了API的項目里,部署完測試下人傻了,日志沒有任何執行了任務的痕跡,調試時候沒毛病。回頭一想,IIS這個懶東西應該是休眠了,直接把我的任務一起回收掉了。淡定的我捋了捋思緒查了查方案,可以更改IIS設置修改定時回收的模式,可以通過訪問站點來喚醒,覺得不是很合適,既然是WindowsServer,那我干脆弄一個WindowsService來定時執行任務再好不過了鴨,而且之前也沒用過.net core寫過WindowsService,正好吃個螃蟹。

一開始我是直接弄了個控制臺程序,按照之前.NET Framework的寫法來寫。后來發現.NET Core專門為這種后臺服務(長時間運行的服務)設計了項目模板,稱之為Worker Service。為了滿足在每日的固定時間點執行,這里選擇老牌的Quartz來實現。簡單描述一下Demo要實現的需求:每日定點向一個API接口中發送信息。

使用Visual Studio(我是使用的VS2019)創建項目,選擇Worker Service(如下圖),姑且就命名為WindowsServiceDemo。

.NET Core開發Windows服務之怎么使用Quartz執行定時任務

項目創建完成之后里面的內容很簡單,一個Program.cs和另一個Work.cs,Work類繼承BackgroundService,并重寫其ExecuteAsync方法。顯而易見,ExecuteAsync方法就是執行后臺任務的入口。

.NET Core開發Windows服務之怎么使用Quartz執行定時任務

Program.cs中,依舊是類型的通過創建一個IHost并啟動運行。為了方便進行依賴注入,可以創建一個IServiceCollection的擴展方法來進行服務的注冊,接下來一步步介紹。

進行服務注冊之前,先將需要引用的包通過Nuget安裝一下。安裝 Quartz 來實現定時執行任務。另外由于需求需要調用api接口即需要使用HttpClient發送請求,所以還需要另外引入包 Microsoft.Extentsions.Http 。由于需要部署成WindowService,需要引入包 Microsoft.Extensions.Hosting.WindowsServices 。

首先定義Job,即執行任務的具體業務邏輯。創建一個SendMsgJob類,繼承IJob接口,并實現Execute方法。Execute方法就是到了設定好的時間點時執行的方法。這里即是實現了使用注冊的HttpClient來發送消息的過程。

public class SendMsgJob : IJob
{
    private readonly AppSettings _appSettings;
    private const string ApiClientName = "ApiClient";
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly ILogger<SendMsgJob> _logger;

    public SendMsgJob(IHttpClientFactory httpClientFactory, IOptions<AppSettings> appSettings, ILogger<SendMsgJob> logger)
    {
        _httpClientFactory = httpClientFactory;
        _logger = logger;
        _appSettings = appSettings.Value;
    }

    /// <summary>
    /// 定時執行
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation($"開始執行定時任務");
        //從httpClientFactory獲取我們注冊的named-HttpClient
        using var client = _httpClientFactory.CreateClient(ApiClientName);
        var message = new
        {
        title = "今日消息",
        content = _appSettings.MessageNeedToSend
        };
        //發送消息
        var response = await client.PostAsync("/msg", new JsonContent(message));
        if (response.IsSuccessStatusCode)
        {
            _logger.LogInformation($"消息發送成功");
        }
    }
}

創建好Job之后,便是設置它讓其定時執行即可。來到Work.cs,替換掉原來的默認演示代碼,換之配置Job執行策略的代碼。使用Quartz配置Job大致分為這么幾部

  1. 創建調度器 Scheduler 

  2. 創建Job實例

  3. 創建觸發器來控制Job的執行策略

  4. 將Job實例和觸發器實例配對注冊進調度器中

  5. 啟動調度器

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("服務啟動");

        //創建一個調度器
        var scheduler = await StdSchedulerFactory.GetDefaultScheduler(stoppingToken);
        //創建Job
        var sendMsgJob = JobBuilder.Create<SendMsgJob>()
        WithIdentity(nameof(SendMsgJob), nameof(Worker))
        Build();
        //創建觸發器
        var sendMsgTrigger = TriggerBuilder.Create()
        WithIdentity("trigger-" + nameof(SendMsgJob), "trigger-group-" + nameof(Worker))
        StartNow()
        WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(08, 30)) //每日的08:30執行
        Build();

        await scheduler.Start(stoppingToken);
        //把Job和觸發器放入調度器中
        await scheduler.ScheduleJob(sendMsgJob, sendMsgTrigger, stoppingToken);
    }
}

關于定時任務的配置告一段落,接下來將所需的服務注冊到服務容器中。根據之前所說的,我們創建一個擴展方法來管理我們需要注冊的服務。

public static class DependencyInject
{
    /// <summary>
    /// 定義擴展方法,注冊服務
    /// </summary>
    public static IServiceCollection AddMyServices(this IServiceCollection services, IConfiguration config)
    {
        //配置文件
        services.Configure<AppSettings>(config);

        //注冊“命名HttpClient”,并為其配置攔截器
        services.AddHttpClient("ApiClient", client =>
        {
            client.BaseAddress = new Uri(config["ApiBaseUrl"]);
        }).AddHttpMessageHandler(_ => new AuthenticRequestDelegatingHandler());

        //注冊任務
        services.AddSingleton<SendMsgJob>();

        return services;
    }
}

修改Program.cs,調用新增的擴展方法

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) =>
            {
                //注冊服務
                services.AddMyServices(hostContext.Configuration)
                AddHostedService<Worker>();
            });
    }
}

到此,主要的代碼就介紹完了。為了調試,可以修改設定好的定時執行時間(比如一分鐘之后),來測試是否能夠成功。修改完觸發器的觸發時間后,直接運行項目。但是遺憾的是,任務并沒有定時觸發。這是什么原因呢?其實是因為雖然我們將我們自定義的Job注入的服務容器,但是調度器創建Job實例時,并不是從我們的服務容器去取的,而是調度器自己走默認的實例化。解決方法是我們為調度器指定JobFactory來重寫實例化Job類型的規則。

首先創建一個MyJobFactory并繼承IJobFactory接口,實現方法 NewJob ,這個方法便是工廠實例化Job的方法,我們可以在這里將實例化Job的方式改寫成從服務容器中獲取實例的方式。

namespace WindowsServiceDemo
{
    /// <summary>
    /// Job工廠,從服務容器中取Job
    /// </summary>
    public class MyJobFactory : 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();
        }
    }
}

隨后將  MyJobFactory 也注冊到服務容器中,即在 AddMyServices 擴展方法中添加

1 //添加Job工廠2 services.AddSingleton<MyJobFactory>();

接下來將調度器的Factory替換成 MyJobFactory ,修改Work.cs代碼如下。

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly MyJobFactory _jobFactory;

    public Worker(ILogger<Worker> logger, MyJobFactory jobFactory)
    {
        _logger = logger;
        _jobFactory = jobFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("服務啟動");

        //創建一個調度器
        var scheduler = await StdSchedulerFactory.GetDefaultScheduler(stoppingToken);

        //指定自定義的JobFactory
        scheduler.JobFactory = _jobFactory;

        //創建Job
        var sendMsgJob = JobBuilder.Create<SendMsgJob>()
        WithIdentity(nameof(SendMsgJob), nameof(Worker))
        Build();
        //創建觸發器
        var sendMsgTrigger = TriggerBuilder.Create()
        WithIdentity("trigger-" + nameof(SendMsgJob), "trigger-group-" + nameof(Worker))
        StartNow()
        WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(08, 30)) //每日的08:30執行
        Build();

        await scheduler.Start(stoppingToken);
        //把Job和觸發器放入調度器中
        await scheduler.ScheduleJob(sendMsgJob, sendMsgTrigger, stoppingToken);
    }
}

在此執行調試,現在一旦到達我們在觸發器中設置的時間點, SendMsgJob 的 Execute 方法便會成功觸發。

開發完成后,現在剩下的任務就是如何將項目發布成一個WindowsService。來到 Program.cs 下,需要進行一些改動

 public static IHostBuilder CreateHostBuilder(string[] args) =>     Host.CreateDefaultBuilder(args)         .UseWindowsService()    //按照Windows Service運行 .ConfigureServices((hostContext, services) =>         {             //注冊服務
             services.AddMyServices(hostContext.Configuration)                     .AddHostedService<Worker>();         });

重新編譯項目成功后,我們便可以使用sc.exe來部署成為windows服務。以管理員身份啟動命令行,執行

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

此時打開服務面板,便可以看到剛剛部署好的 WindowsServiceDemo 服務了。

.NET Core開發Windows服務之怎么使用Quartz執行定時任務

到此,關于“.NET Core開發Windows服務之怎么使用Quartz執行定時任務”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

固安县| 米泉市| 嵊州市| 田阳县| 武鸣县| 新兴县| 台安县| 辽阳县| 拜城县| 韩城市| 长泰县| 玛曲县| 衢州市| 黔江区| 镶黄旗| 大足县| 临西县| 宁波市| 光山县| 乌鲁木齐市| 忻州市| 新昌县| 巴彦县| 东山县| 雷州市| 临高县| 陵水| 长治市| 阜新市| 黑山县| 运城市| 和顺县| 区。| 庆阳市| 宜州市| 蚌埠市| 收藏| 辰溪县| 濮阳县| 徐汇区| 安西县|