后台托管服务

一、IHostedService

1、概述

想要实现后台任务可以实现IHostedService接口或者直接继承BackgroundService抽象类。

IHostedService接口是托管服务接口,在Microsoft.Extensions.Hosting命名空间下面,有两个接口方法:
StartAsync(CancellationToken) :当应用程序主机准备好启动服务时触发该方法
StopAsync(CancellationToken):当应用程序主机执行正常关闭时触发该方法。
 

2、首先需要介绍下Timer
public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period);
  • TimerCallback callback:这是一个委托,指向当定时器触发时要调用的方法。该方法必须有一个object类型的参数,该参数是你传递给Timer构造函数中的state对象。
  • object state:这是一个传递给callback委托的参数。你可以通过这个参数传递任何你需要的数据给callback方法。如果不需要传递任何数据,可以传递null
  • TimeSpan dueTime:这是定时器在首次触发之前应该等待的时间。如果你希望定时器立即开始(即,尽快触发第一次),可以将此值设置为TimeSpan.Zero。如果你希望定时器在将来的某个时间点触发,可以指定一个表示延迟时间的TimeSpan
  • TimeSpan period:这是定时器连续触发之间的时间间隔。如果你不希望定时器周期性地触发(即,只触发一次),可以将此值设置为Timeout.InfiniteTimeSpan
public bool Change(TimeSpan dueTime, TimeSpan period);  
public bool Change(long dueTime, long period);
  • 第一个Change方法接受两个TimeSpan类型的参数,与构造函数中的dueTimeperiod参数相同。
  • 第二个Change方法接受两个long类型的参数,这些参数是dueTimeperiod的毫秒数表示。这对于需要精确控制时间间隔(尤其是当时间间隔非常短或需要精确到毫秒时)很有用。
3、用法示例
public class MyIHostedService : IHostedService, IDisposable
    {
        private Timer _timer;
        private void DoWork(object state)
        {
            Console.WriteLine("DoWork正在运行"+DateTime.Now.ToString());
        }


        public Task StartAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine("StartAsync执行前");
            _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));//立即执行一次,每10秒执行一次
            Console.WriteLine("StartAsync执行后");
            return Task.CompletedTask;// 立即返回Task.CompletedTask,因为StartAsync应该尽快返回 
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine("StopAsync执行前");
            _timer?.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);//停止Timer    
            Console.WriteLine("StopAsync执行后");
            return Task.CompletedTask; 
        }

        public void Dispose()
        {
            _timer?.Dispose();//释放Timer资源 
        }
    }

//program.cs
//注入IHostedService后台服务
builder.Services.AddHostedService<MyIHostedService>();

实现效果

二、BackgroundService

BackgroundService是一个抽象类,这个类实现 IHostedService 接口,并将包含后台任务的具体代码逻辑。该抽象类有一个抽象方法:

  • ExecuteAsync(CancellationToken): 子类需要重写该方法以执行具体的任务处理
1、基础用法示例
public class MyBackgroundService : BackgroundService
    {
        // 当BackgroundService启动时,ExecuteAsync方法将被调用  
        // stoppingToken用于监听取消请求
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    Console.WriteLine("执行前");
                    await Task.Delay(10000, stoppingToken);//模拟工作耗时
                    Console.WriteLine("执行中");
                    Console.WriteLine("执行后");
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex);
                    await Task.Delay(TimeSpan.FromHours(1), stoppingToken);//出现错误,则过一个小时再次执行
                }
            }
        }
    }

//program.cs
builder.Services.AddHostedService<MyBackgroundService>();

控制台

2、实例
public class HostingServices : BackgroundService
    {
        private readonly ClearDataForP_TERMINAL_HT _dataClearer;
        public HostingServices(ClearDataForP_TERMINAL_HT _dataClearer)
        {
            this._dataClearer = _dataClearer; 
        }

        //每隔一小时清除一次数据
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                     
                    await _dataClearer.ClearData();//是一个删除数据的方法,通过依赖注入进来

                    var nextRunTime = DateTime.Now.AddHours(1);//每一个小时执行一次
                    var delayTime = nextRunTime - DateTime.Now;
                    await Task.Delay(delayTime, stoppingToken);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message.ToString());
                    await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
                }
            }
        }
    }


三、QuartZ.Net

1、概述

Quartz.NET 里有三个非常重要的概念:任务,触发器 和 调度器,对应着 Job,Trigger 和Scheduler 

1.1、Job 表示一个你需要被执行的任务,任务中可以写上你的业务逻辑代码,Job 就是一个实现了 IJob 接口的子类。
1.2、Trigger 通常用于指定一个 job 是如何被调度的? 什么意思呢? 比如说:这个job是按天执行? 还是按小时执行?还是按秒执行?值得注意的是因为支持了 Cron 表达式,还能够实现更加超级复杂的调度逻辑。

1.3、Scheduler 通常按照你预先设置的调度规则将 job 丢给它的任务队列,并按照 trigger 规则轮询然后执行任务。

2、简单实现

2.1、nuget包  Quartz

2.2、自定义类

using Quartz;
using Quartz.Impl;

namespace IHostedService_lianxi
{
    public class MyQuartZ:IHostedService
    {

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            //创建调度器工厂
            var factory = new StdSchedulerFactory();

            //从工厂中获取调度器
            IScheduler scheduler = await factory.GetScheduler();

            //定义作业详情
            IJobDetail job = JobBuilder.Create<MyJob>()
                .WithIdentity("myjob", "group1")
                .Build();

            //定义触发器
            //1、定义一个简单触发器
            var trigger1 = TriggerBuilder.Create()
                            .WithIdentity("myTrigger", "group1")
                            .WithSimpleSchedule(o =>
                            {
                                o.WithRepeatCount(3)//循环次数
                                .WithIntervalInSeconds(10);//每10秒执行一次
                            }).Build();
            //2、创建Cron触发器(Cron触发器比简答触发器更加强大)
            var trigger2 = TriggerBuilder.Create()
                            .WithCronSchedule("* * * * * ? *")
                            .Build();

            //告诉调度器去调度我们的作业
            await scheduler.ScheduleJob(job, trigger1);

            //启动调度器
            await scheduler.Start();
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            //结束时调用的
        }
    }

    //自定义我的job
    public class MyJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            Console.WriteLine("MyJob执行中");
            await Task.Delay(5000);
            //return Task.CompletedTask;
        }
    }
}


//program.cs
//注入IHostedService后台服务
builder.Services.AddHostedService<MyQuartZ>();

控制台

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值