真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

.NETCore開發(fā)Windows服務(wù)之怎么使用Quartz執(zhí)行定時任務(wù)

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

專注于為中小企業(yè)提供網(wǎng)站設(shè)計制作、成都網(wǎng)站設(shè)計服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)平南免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了上1000家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。

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

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

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

.NET Core開發(fā)Windows服務(wù)之怎么使用Quartz執(zhí)行定時任務(wù)

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

.NET Core開發(fā)Windows服務(wù)之怎么使用Quartz執(zhí)行定時任務(wù)

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

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

首先定義Job,即執(zhí)行任務(wù)的具體業(yè)務(wù)邏輯。創(chuàng)建一個SendMsgJob類,繼承IJob接口,并實現(xiàn)Execute方法。Execute方法就是到了設(shè)定好的時間點時執(zhí)行的方法。這里即是實現(xiàn)了使用注冊的HttpClient來發(fā)送消息的過程。

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;
    }

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

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

  1. 創(chuàng)建調(diào)度器 Scheduler 

  2. 創(chuàng)建Job實例

  3. 創(chuàng)建觸發(fā)器來控制Job的執(zhí)行策略

  4. 將Job實例和觸發(fā)器實例配對注冊進(jìn)調(diào)度器中

  5. 啟動調(diào)度器

public class Worker : BackgroundService
{
    private readonly ILogger _logger;

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

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

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

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

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

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

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

        //注冊任務(wù)
        services.AddSingleton();

        return services;
    }
}

修改Program.cs,調(diào)用新增的擴展方法

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

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

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

namespace WindowsServiceDemo
{
    /// 
    /// Job工廠,從服務(wù)容器中取Job
    /// 
    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 也注冊到服務(wù)容器中,即在 AddMyServices 擴展方法中添加

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

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

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("服務(wù)啟動");

        //創(chuàng)建一個調(diào)度器
        var scheduler = await StdSchedulerFactory.GetDefaultScheduler(stoppingToken);

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

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

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

在此執(zhí)行調(diào)試,現(xiàn)在一旦到達(dá)我們在觸發(fā)器中設(shè)置的時間點, SendMsgJob 的 Execute 方法便會成功觸發(fā)。

開發(fā)完成后,現(xiàn)在剩下的任務(wù)就是如何將項目發(fā)布成一個WindowsService。來到 Program.cs 下,需要進(jìn)行一些改動

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

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

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

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

.NET Core開發(fā)Windows服務(wù)之怎么使用Quartz執(zhí)行定時任務(wù)

到此,關(guān)于“.NET Core開發(fā)Windows服務(wù)之怎么使用Quartz執(zhí)行定時任務(wù)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
分享題目:.NETCore開發(fā)Windows服務(wù)之怎么使用Quartz執(zhí)行定時任務(wù)
分享鏈接:http://weahome.cn/article/jeoigg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部